public/Update-NexposeSiteScanSchedule.ps1

Function Update-NexposeSiteScanSchedule {
<#
    .SYNOPSIS
        Creates a new scan schedule for the specified site
 
    .DESCRIPTION
        Creates a new scan schedule for the specified site
 
    .PARAMETER SiteId
        The identifier of the site
 
    .PARAMETER ScheduleId
        The identifier of the scan schedule
 
    .PARAMETER Enabled
        Flag indicating whether the scan schedule is enabled
 
    .PARAMETER Name
        A user-defined name for the scan launched by the schedule
 
    .PARAMETER StartDate
        The scheduled start date. Date is represented in yyyy-MM-dd format. Repeating schedules will determine the next schedule to begin based on this date
 
    .PARAMETER StartTime
        The scheduled start time. Time is represented in hh:mm format. Repeating schedules will determine the next schedule to begin based on this time
 
    .PARAMETER Frequency
        Settings for repeating a scheduled task. Text starts with either 'Once' or 'Every'.
        Examples include: 'Once', 'Every hour', 'Every day', 'Every 2 hours', 'Every 2 days', 'Every Monday', 'Every week', 'Every 3 weeks', 'Every 31st of the month', 'Every 31st of the month repeated every 3 months', 'Every 2nd Monday of the month', 'Every 1st Monday of the month repeated every 3 months', 'Every Monday repeated every 3 weeks'
 
    .PARAMETER Duration
        Specifies the maximum duration the scheduled scan is allowed to run. Scheduled scans that do not complete within specified duration will be paused.
        The scan duration are represented by the format '[n]D[n]H[n]M'. In these representations, the [n] is replaced by a value for each of the date and time elements that follow the [n]
        Maximum values are: 364 Days, 23 Hours, 59 Minutes. Examples inclue: '2d', '2h30m', '1w3d', ''
 
    .PARAMETER ScanRepeat
        Specifies the desired behavior of a repeating scheduled scan when the previous scan was paused due to reaching is maximum duration. The following table describes each supported value
 
    .PARAMETER ScanTemplate
        The identifier of the scan template to be used for this scan schedule. If not set, the site's assigned scan template will be used
 
    .PARAMETER ScanEngine
        The identifier of the scan engine to be used for this scan schedule. If not set, the site's assigned scan engine will be used
 
    .PARAMETER Assets
        Allows one or more assets defined within the site to be scanned for this scan schedule. This property is only supported for static sites. When this property is null, or not defined in schedule, then all assets defined in the static site will be scanned
 
    .EXAMPLE
        Update-NexposeSiteScanSchedule -SiteId 1 -ScheduleId 1 -Name 'Just the once' -StartDate '2019-01-01' -StartTime '00:01' -ReachesDuration restart-scan -Frequency 'Once' -Duration '1h'
        Run just one scan at the start of the year for a maximum of one hour
 
    .EXAMPLE
        Update-NexposeSiteScanSchedule -SiteId 1 -ScheduleId 2 -Name 'Every Day' -StartDate '2019-01-01' -StartTime '00:01' -ReachesDuration restart-scan -Frequency 'Every Day' -Duration '1h'
        Run a scan every single day
 
    .EXAMPLE
        Update-NexposeSiteScanSchedule -SiteId 1 -ScheduleId 3 -Name 'Every Day' -StartDate '2019-01-01' -StartTime '00:01' -ReachesDuration restart-scan -Frequency 'Every 31st of the month repeated every 3 months' -Duration '1h'
        Run a scan every 1st of the month, every 3 months
 
    .NOTES
        For additional information please see my GitHub wiki page
 
    .FUNCTIONALITY
        PUT: sites/{id}/scan_schedules/{scheduleId}
 
    .LINK
        https://github.com/My-Random-Thoughts/Rapid7Nexpose
#>


    [CmdletBinding(SupportsShouldProcess)]
    Param (
        [Parameter(Mandatory = $true)]
        [int]$SiteId,

        [Parameter(Mandatory = $true)]
        [int]$ScheduleId,

        [switch]$Enabled,

        [Parameter(Mandatory = $true)]
        [string]$Name,

        [Parameter(Mandatory = $true)]
        [ValidateScript({[datetime]::ParseExact($_, 'yyyy-MM-dd', $null)})]
        $StartDate,

        [Parameter(Mandatory = $true)]
        [ValidateScript({[datetime]::ParseExact($_, 'hh:mm', $null)})]
        $StartTime,

        [string]$Frequency,

        [ValidatePattern('^((?:[1-9][0-9]?|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-4])D)? ?((?:1?[0-9]?|2[0-3])H)? ?((?:[1-4]?[0-9]?|5[0-9])M)?$')]
        [string]$Duration,

        [ValidateSet('restart-scan','resume-scan')]
        [string]$ScanRepeat,

        [object]$Assets    # @{ includedTargets=@(); excludedTargets=@(); includedAssetGroups=@(); excludedAssetGroups=@() }
    )

    DynamicParam {
        $dynParam = (New-Object -Type 'System.Management.Automation.RuntimeDefinedParameterDictionary')
                             New-DynamicParameter -Dictionary $dynParam -Name 'ScanTemplate' -Type 'string' -ValidateSet @((Get-NexposeScanTemplate              ).id)
        If ($SiteId -gt 0) { New-DynamicParameter -Dictionary $dynParam -Name 'ScanEngine'   -Type 'int'    -ValidateSet @((Get-NexposeScanEngine -SiteId $SiteId).id) }
        Return $dynParam
    }

    Begin {
        # Define variables for dynamic parameters
        [string]$ScanTemplate = $($PSBoundParameters.ScanTemplate)
        [string]$ScanEngine   = $($PSBoundParameters.ScanEngine  )
        If ([string]::IsNullOrEmpty($ScanTemplate) -eq $true) { $ScanTemplate = 'discovery' }

        $matchInterval = (Test-FrequencyString -Frequency $Frequency)
        If ($matchInterval.Success -eq $false) { Throw 'Invalid Frequency entered, please see the examples for more information.' }
    }

    Process {
        $apiQuery = @{
            enabled        = ($Enabled.IsPresent)
            scanName       =  $Name
            onScanRepeat   =  $ScanRepeat
            scanTemplateId =  $ScanTemplate
            start          = ('{0}T{1}:00Z' -f $StartDate, $StartTime)
        }

        If ([string]::IsNullOrEmpty($ScanEngine) -eq $false) {
            $apiQuery += @{
               scanEngineId = $ScanEngine
            }
        }

        $converted = (Convert-FrequencyString -Frequency $Frequency)
        If ($null -ne $converted) { $apiQuery += $converted}

        If ([string]::IsNullOrEmpty($Duration) -eq $false) {
            [string]$convertedDuration = (Convert-TimeSpan -Duration $Duration)
            If ($convertedDuration) {
                $apiQuery.duration = $convertedDuration
            }
        }

        If ([string]::IsNullOrEmpty($Assets) -eq $false) {
            $apiQuery += @{ assets = @{} }
            If ([string]::IsNullOrEmpty($Assets.includedTargets)     -eq $false) { $apiQuery.assets += @{ includedTargets =     @{ addresses     = $Assets.includedTargets     }}}
            If ([string]::IsNullOrEmpty($Assets.excludedTargets)     -eq $false) { $apiQuery.assets += @{ excludedTargets =     @{ addresses     = $Assets.excludedTargets     }}}
            If ([string]::IsNullOrEmpty($Assets.includedAssetGroups) -eq $false) { $apiQuery.assets += @{ includedAssetGroups = @{ assetGroupIDs = $Assets.includedAssetGroups }}}
            If ([string]::IsNullOrEmpty($Assets.excludedAssetGroups) -eq $false) { $apiQuery.assets += @{ excludedAssetGroups = @{ assetGroupIDs = $Assets.excludedAssetGroups }}}
        }

        If ($PSCmdlet.ShouldProcess($Name)) {
            Write-Output (Invoke-NexposeQuery -UrlFunction "sites/$SiteId/scan_schedules/$ScheduleId" -ApiQuery $apiQuery -RestMethod Put)
        }
    }

    End {
    }
}