IdentityCommand.RiskMgmt.psm1
|
# .ExternalHelp IdentityCommand.RiskMgmt-help.xml function Connect-RMTenant { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Subdomain')] param( #subdomain [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Subdomain')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'SubdomainCredential')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'SubdomainSAML')] [ValidateNotNullOrEmpty()] [Alias('subdomain')] [String]$tenant_subdomain, #tenant_url [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URL')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URLCredential')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URLSAML')] [ValidateNotNullOrEmpty()] [Alias('compass_url','risk_url')] [String]$tenant_url, #Credential used to authenticate to CyberArk Identity. Authentication is performed even if an active IdentityCommand session is found, replacing it [parameter(Mandatory = $true, ParameterSetName = 'SubdomainCredential')] [parameter(Mandatory = $true, ParameterSetName = 'URLCredential')] [ValidateNotNullOrEmpty()] [PSCredential]$Credential, #Authenticate as a service user via New-IDPlatformToken (OAuth client_credentials) instead of the interactive New-IDSession [parameter(ParameterSetName = 'SubdomainCredential')] [parameter(ParameterSetName = 'URLCredential')] [Switch]$PlatformToken, #SAML assertion used to authenticate to CyberArk Identity. Authentication is performed even if an active IdentityCommand session is found, replacing it [parameter(Mandatory = $true, ParameterSetName = 'SubdomainSAML')] [parameter(Mandatory = $true, ParameterSetName = 'URLSAML')] [ValidateNotNullOrEmpty()] [String]$SAMLResponse ) begin { $IDSession = Get-IDSession $HaveSession = $null -ne $IDSession.tenant_url $AuthRequested = $PSBoundParameters.ContainsKey('Credential') -or $PSBoundParameters.ContainsKey('SAMLResponse') if ($HaveSession -and $AuthRequested) { Write-Verbose 'Authentication parameters were supplied; authenticating and replacing the existing IdentityCommand session' } }#begin process { $UsingSubdomain = $PSCmdlet.ParameterSetName -like 'Subdomain*' #Resolve service URLs from platform discovery when a subdomain was supplied, or when #authentication is required and the CyberArk Identity URL must be discovered. $ServiceUrl = $null if ($UsingSubdomain) { $ServiceUrl = Resolve-ServiceUrl -Service compass -Subdomain $tenant_subdomain $tenant_url = $ServiceUrl.ServiceUrl } else { #Ensure URL is in expected format - remove trailing slash if provided in Url $tenant_url = $tenant_url -replace '/$', '' if ($AuthRequested) { $ServiceUrl = Resolve-ServiceUrl -Service compass -Url $tenant_url } } if ($AuthRequested -or (-not $HaveSession)) { if (-not $AuthRequested) { throw 'Authenticate with New-IDSession or New-IDPlatformToken, or supply -Credential, and try again' } $IdentityUrl = $ServiceUrl.IdentityUrl if ($PSCmdlet.ShouldProcess($IdentityUrl, 'Authenticate to CyberArk Identity')) { if ($PSCmdlet.ParameterSetName -like '*SAML') { $null = New-IDSession -tenant_url $IdentityUrl -SAMLResponse $SAMLResponse } elseif ($PlatformToken) { $null = New-IDPlatformToken -tenant_url $IdentityUrl -Credential $Credential } else { $null = New-IDSession -tenant_url $IdentityUrl -Credential $Credential } $IDSession = Get-IDSession } } #Make the CyberArk Identity Session available in the IdentityCommand.RiskMgmt scope foreach ($key in $IDSession.keys) { if ($null -ne $IDSession[$key]) { $ISPSSSession[$key] = $IDSession[$key] } } #Set the Risk Management URL in the session data $ISPSSSession.tenant_url = $tenant_url }#process end { }#end } # .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 = "$($ISPSSSession.tenant_url)/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 )] [ValidateRange(0, 2147483647)] [int]$offset, [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 = "$($ISPSSSession.tenant_url)/api/risks/findings" #TODO: array filters travel as a percent encoded, comma joined single value #(severity=CRITICAL%2CHIGH). The spec sets no style/explode, whose OpenAPI default is one #parameter per value. Verify against a tenant. $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 = "$($ISPSSSession.tenant_url)/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 = "$($ISPSSSession.tenant_url)/api/recommendations/$recommendationType/by-tags" #TODO: array filters travel as a percent encoded, comma joined single value #(severity=CRITICAL%2CHIGH). The spec sets no style/explode, whose OpenAPI default is one #parameter per value. Verify against a tenant. $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 )] [ValidateRange(0, 2147483647)] [int]$offset, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateCount(1, 10)] [String[]]$entityTypes, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateCount(1, 100)] [String[]]$ids ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/remediations" #TODO: array filters travel as a percent encoded, comma joined single value #(severity=CRITICAL%2CHIGH). The spec sets no style/explode, whose OpenAPI default is one #parameter per value. Verify against a tenant. $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 = "$($ISPSSSession.tenant_url)/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 = "$($ISPSSSession.tenant_url)/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 = "$($ISPSSSession.tenant_url)/api/risks/progress" #TODO: array filters travel as a percent encoded, comma joined single value #(severity=CRITICAL%2CHIGH). The spec sets no style/explode, whose OpenAPI default is one #parameter per value. Verify against a tenant. $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 = "$($ISPSSSession.tenant_url)/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 )] [ValidateRange(0, 2147483647)] [int]$offset, [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 = "$($ISPSSSession.tenant_url)/api/risks/risk-types" #TODO: array filters travel as a percent encoded, comma joined single value #(severity=CRITICAL%2CHIGH). The spec sets no style/explode, whose OpenAPI default is one #parameter per value. Verify against a tenant. $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 = "$($ISPSSSession.tenant_url)/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 = "$($ISPSSSession.tenant_url)/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 = "$($ISPSSSession.tenant_url)/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 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 |