IdentityCommand.RiskMgmt.psm1

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMEntityRiskSummary {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias('entity-id', 'id')]
        [String]$entityId
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/entities/$entityId"

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMFinding {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 1000)]
        [int]$limit,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidatePattern('^[a-zA-Z0-9_]+:(asc|desc)$')]
        [String]$sort,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 200)]
        [String]$search,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 10)]
        [String[]]$riskTypeId,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 4)]
        [ValidateSet('OPEN', 'CLOSED', 'SNOOZED')]
        [String[]]$status,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 4)]
        [ValidateSet('LOW', 'MEDIUM', 'HIGH', 'CRITICAL')]
        [String[]]$severity,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 10)]
        [String[]]$entityTypes,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 50)]
        [String[]]$entityId,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 50)]
        [String[]]$targetId,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 365)]
        [int]$daysSinceLastUpdate
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/findings"

        $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter)

        #Send Request
        $result = Invoke-IDRestMethod -Uri $URI -Method GET

        if ($null -ne $result) {

            Get-PagedResult -InitialResult $result -URI $URI -Style Offset -ResultProperty 'findings' -LastPageKey 'isLastPage'

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMModuleData {

    [CmdletBinding()]
    param()

    begin { }#begin

    process {

        #Calculate the time elapsed since the start of the session and include in return data
        if ($null -ne $ISPSSSession.StartTime) {
            $ISPSSSession.ElapsedTime = '{0:HH:mm:ss}' -f ([datetime]$($(Get-Date) - $($ISPSSSession.StartTime)).Ticks)
        } else { $ISPSSSession.ElapsedTime = $null }

        #Deep Copy the $ISPSSSession session object and return as IdCmd Session type.
        Get-SessionClone -InputObject $ISPSSSession | Add-CustomType -Type IdCmd.Session

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRecommendation {
    [CmdletBinding()]
    param()

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/recommendations"

        #Send Request
        $result = Invoke-IDRestMethod -Uri $URI -Method GET

        if ($null -ne $result) {

            $result.recommendations

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRecommendationTagCount {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [String]$recommendationType,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 5)]
        [String[]]$entityTags
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/recommendations/$recommendationType/by-tags"

        $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter -ParametersToRemove recommendationType)

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRemediation {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 1000)]
        [int]$limit,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 10)]
        [String[]]$entityTypes,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 100)]
        [String[]]$ids
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/remediations"

        $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter)

        #Send Request
        $result = Invoke-IDRestMethod -Uri $URI -Method GET

        if ($null -ne $result) {

            Get-PagedResult -InitialResult $result -URI $URI -Style Offset -ResultProperty 'remediations' -LastPageKey 'isLastPage'

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRiskPostureDiscovery {
    [CmdletBinding()]
    param()

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risk-posture/secure-standing-privilege/discovery"

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRiskPostureProgress {
    [CmdletBinding()]
    param()

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risk-posture/secure-standing-privilege/progress"

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRiskProgress {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 10)]
        [String[]]$entityTypes
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/progress"

        $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter)

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRiskSummary {
    [CmdletBinding()]
    param()

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/summary"

        #Send Request
        Invoke-IDRestMethod -Uri $URI -Method GET

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Get-RMRiskType {
    [CmdletBinding()]
    param(
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 1000)]
        [int]$limit,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidatePattern('^[a-zA-Z0-9_]+:(asc|desc)$')]
        [String]$sort,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 200)]
        [String]$search,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 4)]
        [ValidateSet('LOW', 'MEDIUM', 'HIGH', 'CRITICAL')]
        [String[]]$severity,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 10)]
        [String[]]$entityTypes,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 50)]
        [String[]]$entityId,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateCount(1, 50)]
        [String[]]$targetId,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 365)]
        [int]$daysSinceLastUpdate
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/risk-types"

        $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter)

        #Send Request
        $result = Invoke-IDRestMethod -Uri $URI -Method GET

        if ($null -ne $result) {

            Get-PagedResult -InitialResult $result -URI $URI -Style Offset -ResultProperty 'riskTypes' -LastPageKey 'isLastPage'

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function New-RMRemediation {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [String]$entityType,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 200)]
        [String]$name,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 2000)]
        [String]$remediationText,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 2048)]
        [String]$link
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/remediations"

        $body = $PSBoundParameters | Get-Parameter | ConvertTo-Json -Depth 8

        if ($PSCmdlet.ShouldProcess($name, 'Create Remediation')) {

            #Send Request
            Invoke-IDRestMethod -Uri $URI -Method POST -Body $body

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Resume-RMFinding {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias('finding-id', 'id')]
        [String]$findingId
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/findings/$findingId/snooze"

        if ($PSCmdlet.ShouldProcess($findingId, 'Remove Snooze From Finding')) {

            #Send Request
            Invoke-IDRestMethod -Uri $URI -Method DELETE

        }

    }#process

    end { }#end

}

# .ExternalHelp IdentityCommand.RiskMgmt-help.xml
function Suspend-RMFinding {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias('finding-id', 'id')]
        [String]$findingId,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateRange(1, 365)]
        [int]$durationDays,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateLength(1, 1000)]
        [String]$reason
    )

    begin { }#begin

    process {

        $URI = "$(Resolve-RequestUrl)/api/risks/findings/$findingId/snooze"

        $body = $PSBoundParameters | Get-Parameter -ParametersToRemove findingId | ConvertTo-Json -Depth 8

        if ($PSCmdlet.ShouldProcess($findingId, 'Snooze Finding')) {

            #Send Request
            Invoke-IDRestMethod -Uri $URI -Method POST -Body $body

        }

    }#process

    end { }#end

}

#Copy IdentityCommand's private helpers into this module: this module's functions call them, and
#the argument completer registrations below do so at import time.
#Each copy is created from the function definition, so it runs in this module's scope and uses this
#module's $ISPSSSession, whether IdentityCommand loaded from source or from its combined psm1.
#Resolve a single IdentityCommand module: with more than one version loaded, Get-Module returns
#an array.
$Module = Get-Module -Name IdentityCommand | Sort-Object Version -Descending | Select-Object -First 1

if ($null -eq $Module) {
    throw 'The IdentityCommand module is not loaded. Import IdentityCommand and try again.'
}

& $Module { Get-ChildItem -Path Function: } |

    Where-Object { $_.ModuleName -eq $Module.Name -and -not $Module.ExportedFunctions.ContainsKey($_.Name) } |

    ForEach-Object {

        . ([scriptblock]::Create("function $($_.Name) {$($_.Definition)}"))

    }

#region Registration

#entityTypes is documented with four allowed values but typed as a free string in the spec, so it
#is offered as a completion rather than enforced with a ValidateSet.
$EntityTypeCompleter = {
    $wordToComplete = $args[2]
    @('USER', 'FEDERATED_USER', 'FEDERATED_GROUP', 'WEBAPP') |
        ForEach-Object { [pscustomobject]@{ entityType = $_ } } |
        Get-CompletionResult -WordToComplete $wordToComplete -ValueProperty entityType
}

Register-ArgumentCompleter -ParameterName 'entityTypes' -ScriptBlock $EntityTypeCompleter -CommandName @(
    'Get-RMFinding'
    'Get-RMRemediation'
    'Get-RMRiskProgress'
    'Get-RMRiskType'
)

Register-ArgumentCompleter -ParameterName 'entityType' -ScriptBlock $EntityTypeCompleter -CommandName 'New-RMRemediation'

Register-ArgumentCompleter -ParameterName 'recommendationType' -ScriptBlock (
    Get-ArgumentCompleter -RetrievalCommand 'Get-RMRecommendation' -ValueProperty 'recommendationType'
) -CommandName 'Get-RMRecommendationTagCount'

Register-ArgumentCompleter -ParameterName 'ids' -ScriptBlock (
    Get-ArgumentCompleter -RetrievalCommand 'Get-RMRemediation' -ValueProperty 'id' -LabelProperty 'name'
) -CommandName 'Get-RMRemediation'

#endregion Registration

# Script scope session object for session data
$ISPSSSession = [ordered]@{
    tenant_url         = $null
    User               = $null
    TenantId           = $null
    SessionId          = $null
    Subdomain          = $null
    WebSession         = $null
    StartTime          = $null
    ElapsedTime        = $null
    LastCommand        = $null
    LastCommandTime    = $null
    LastCommandResults = $null
    LastError          = $null
    LastErrorTime      = $null
} | Add-CustomType -Type IdCmd.Session

New-Variable -Name ISPSSSession -Value $ISPSSSession -Scope Script -Force

#Discovery key for Resolve-RequestUrl
New-Variable -Name ServiceKey -Value 'compass' -Scope Script -Force

#Discovery endpoint for Resolve-RequestUrl
New-Variable -Name ServiceEndpoint -Value 'bootstrap' -Scope Script -Force