modules/Devolutions.CIEM.Graph/Public/Get-CIEMConnectorPayloadPreview.ps1
|
function AssertCIEMConnectorSourceProperty { [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Source, [Parameter(Mandatory)] [string]$Name, [Parameter(Mandatory)] [string]$SignalType ) $ErrorActionPreference = 'Stop' if ($null -eq $Source.PSObject.Properties[$Name]) { throw "$SignalType connector preview source is missing required property '$Name'." } } function GetCIEMConnectorAction { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$SignalType, [Parameter(Mandatory)] [string]$SourceType ) $ErrorActionPreference = 'Stop' if ($SignalType -eq 'NeedsAttention') { switch ($SourceType) { 'Identity' { return @{ Action = 'ReviewIdentity'; Route = '/ciem/identities' } } 'AttackPath' { return @{ Action = 'ReviewAttackPath'; Route = '/ciem/attack-paths' } } default { throw "Unsupported NeedsAttention connector preview source type '$SourceType'." } } } if ($SignalType -eq 'ExposureChange') { switch ($SourceType) { 'IdentityRisk' { return @{ Action = 'ReviewIdentity'; Route = '/ciem/identities' } } 'AttackPath' { return @{ Action = 'ReviewAttackPath'; Route = '/ciem/attack-paths' } } default { throw "Unsupported ExposureChange connector preview source type '$SourceType'." } } } throw "Unsupported connector preview signal type '$SignalType'." } function NewCIEMConnectorPayloadPreview { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet('Alert', 'SIEM', 'Webhook', 'PSU')] [string]$ConnectorType, [Parameter(Mandatory)] [ValidateSet('NeedsAttention', 'ExposureChange')] [string]$SignalType, [Parameter(Mandatory)] [object]$Signal ) $ErrorActionPreference = 'Stop' foreach ($propertyName in @('SourceId', 'SourceType', 'Severity', 'SeverityRank', 'Title', 'IdentityId', 'Identity', 'IdentityType', 'TargetId', 'Target', 'Reason', 'Evidence')) { AssertCIEMConnectorSourceProperty -Source $Signal -Name $propertyName -SignalType $SignalType } $action = GetCIEMConnectorAction -SignalType $SignalType -SourceType ([string]$Signal.SourceType) $eventName = switch ($SignalType) { 'NeedsAttention' { 'ciem.risk.needs_attention' } 'ExposureChange' { 'ciem.exposure.changed' } } $summary = "$($Signal.Severity) $SignalType signal for $($Signal.Identity): $($Signal.Reason)" $payload = [ordered]@{ schemaVersion = 'devolutions.ciem.signal.preview.v1' previewOnly = $true deliveryEnabled = $false connectorType = $ConnectorType eventName = $eventName signalType = $SignalType sourceId = [string]$Signal.SourceId sourceType = [string]$Signal.SourceType severity = [string]$Signal.Severity severityRank = [int]$Signal.SeverityRank title = [string]$Signal.Title summary = $summary identity = [ordered]@{ id = [string]$Signal.IdentityId name = [string]$Signal.Identity type = [string]$Signal.IdentityType } target = [ordered]@{ id = [string]$Signal.TargetId name = [string]$Signal.Target } reason = [string]$Signal.Reason evidence = [string]$Signal.Evidence review = [ordered]@{ action = [string]$action.Action route = [string]$action.Route } } switch ($ConnectorType) { 'Alert' { $payload.connectorPreview = [ordered]@{ title = "$($Signal.Severity): $($Signal.Title)" body = $summary } } 'SIEM' { $payload.connectorPreview = [ordered]@{ eventCategory = 'cloud.entitlement' eventAction = $eventName eventSeverity = [int]$Signal.SeverityRank message = $summary } } 'Webhook' { $payload.connectorPreview = [ordered]@{ method = 'POST' body = 'json' } } 'PSU' { $payload.connectorPreview = [ordered]@{ app = 'Devolutions CIEM' action = [string]$action.Action route = [string]$action.Route } } } [PSCustomObject]@{ Id = "$ConnectorType`:$SignalType`:$($Signal.SourceId)" ConnectorType = $ConnectorType SignalType = $SignalType EventName = $eventName Severity = [string]$Signal.Severity SeverityRank = [int]$Signal.SeverityRank Title = [string]$Signal.Title Summary = $summary ReviewAction = [string]$action.Action ReviewRoute = [string]$action.Route PayloadJson = ($payload | ConvertTo-Json -Depth 10 -Compress) } } function ConvertCIEMNeedsAttentionToConnectorSignal { [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Item ) $ErrorActionPreference = 'Stop' [PSCustomObject]@{ SourceId = [string]$Item.Id SourceType = [string]$Item.SourceType Severity = [string]$Item.Severity SeverityRank = [int]$Item.SeverityRank Title = [string]$Item.Title IdentityId = [string]$Item.IdentityId Identity = [string]$Item.Identity IdentityType = [string]$Item.IdentityType TargetId = [string]$Item.TargetId Target = [string]$Item.Target Reason = [string]$Item.Reason Evidence = [string]$Item.Evidence } } function ConvertCIEMExposureChangeToConnectorSignal { [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Change ) $ErrorActionPreference = 'Stop' $reason = switch ([string]$Change.ChangeType) { 'NewRisk' { "New $($Change.CurrentSeverity) exposure detected" } 'RiskIncrease' { "Exposure increased from $($Change.PreviousSeverity) to $($Change.CurrentSeverity)" } 'RemovedRisk' { "Previously observed $($Change.PreviousSeverity) exposure was removed" } default { throw "Unsupported exposure change type '$($Change.ChangeType)'." } } [PSCustomObject]@{ SourceId = [string]$Change.Id SourceType = [string]$Change.ExposureType Severity = [string]$Change.Severity SeverityRank = [int]$Change.SeverityRank Title = [string]$Change.Title IdentityId = [string]$Change.ImpactedIdentityId Identity = [string]$Change.ImpactedIdentityName IdentityType = [string]$Change.ImpactedIdentityType TargetId = [string]$Change.ImpactedResourceId Target = [string]$Change.ImpactedResourceName Reason = $reason Evidence = [string]$Change.Evidence } } function Get-CIEMConnectorPayloadPreview { <# .SYNOPSIS Returns local preview payloads for outbound CIEM signal connectors. .DESCRIPTION Formats current Needs Attention and exposure-change signals into preview-only payload envelopes for Alert, SIEM, Webhook, and PSU connector shapes. This command does not send data and does not read connector target settings. .PARAMETER ConnectorType Connector preview family to render. .PARAMETER SignalType Signal source to format. All includes Needs Attention and Exposure Change signals. .PARAMETER Limit Maximum number of source signals to read from each selected source. #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [Parameter()] [ValidateSet('Alert', 'SIEM', 'Webhook', 'PSU')] [string[]]$ConnectorType = @('Alert', 'SIEM', 'Webhook', 'PSU'), [Parameter()] [ValidateSet('All', 'NeedsAttention', 'ExposureChange')] [string]$SignalType = 'All', [Parameter()] [ValidateRange(1, 100)] [int]$Limit = 10 ) $ErrorActionPreference = 'Stop' $signals = @() if ($SignalType -in @('All', 'NeedsAttention')) { foreach ($item in @(Get-CIEMDashboardNeedsAttention -Limit $Limit)) { $signals += [PSCustomObject]@{ SignalType = 'NeedsAttention' Signal = ConvertCIEMNeedsAttentionToConnectorSignal -Item $item } } } if ($SignalType -in @('All', 'ExposureChange')) { foreach ($change in @(Get-CIEMExposureChange -Last $Limit)) { $signals += [PSCustomObject]@{ SignalType = 'ExposureChange' Signal = ConvertCIEMExposureChangeToConnectorSignal -Change $change } } } @( foreach ($signal in $signals) { foreach ($type in $ConnectorType) { NewCIEMConnectorPayloadPreview -ConnectorType $type -SignalType ([string]$signal.SignalType) -Signal $signal.Signal } } ) } |