modules/Devolutions.CIEM.Graph/Tests/Unit/CIEMAttackPathRemediation.Tests.ps1
|
BeforeAll { Remove-Module Devolutions.CIEM -Force -ErrorAction SilentlyContinue Import-Module (Join-Path $PSScriptRoot '..' '..' '..' '..' 'Devolutions.CIEM.psd1') Mock -ModuleName Devolutions.CIEM Write-CIEMLog {} } Describe 'Invoke-CIEMAttackPathRemediation' { Context 'Command structure' { It 'Is available as a public command' { Get-Command Invoke-CIEMAttackPathRemediation -Module Devolutions.CIEM -ErrorAction Stop | Should -Not -BeNullOrEmpty } It 'Has mandatory AttackPath parameter that accepts pipeline input' { $param = (Get-Command Invoke-CIEMAttackPathRemediation).Parameters['AttackPath'] $param | Should -Not -BeNullOrEmpty $parameterAttribute = @($param.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] })[0] $parameterAttribute.Mandatory | Should -BeTrue $parameterAttribute.ValueFromPipeline | Should -BeTrue } It 'Supports ShouldProcess for -WhatIf and -Confirm' { $command = Get-Command Invoke-CIEMAttackPathRemediation $command.Parameters.ContainsKey('WhatIf') | Should -BeTrue $command.Parameters.ContainsKey('Confirm') | Should -BeTrue } } Context 'Execution behavior' { It 'Executes remediation script and returns completion metadata' { $filePath = Join-Path $TestDrive 'attack-path-remediation-executed.txt' $attackPath = InModuleScope Devolutions.CIEM -Parameters @{ filePath = $filePath } { param($filePath) $item = [CIEMAttackPath]::new() $item.PatternId = 'open-management-port' $item.PatternName = 'Management port open to the internet' $item.RemediationScriptPath = 'modules/Devolutions.CIEM.Graph/Data/attack_path_remediation_scripts/management-port-open-to-the-internet.ps1' $escapedPath = $filePath.Replace("'", "''") $item.RemediationScript = "Set-Content -Path '$escapedPath' -Value 'executed'" $item } $result = $attackPath | Invoke-CIEMAttackPathRemediation -Confirm:$false $filePath | Should -Exist ((Get-Content $filePath -Raw).Trim()) | Should -Be 'executed' $result.PatternId | Should -Be 'open-management-port' $result.PatternName | Should -Be 'Management port open to the internet' $result.RemediationScriptPath | Should -Be 'modules/Devolutions.CIEM.Graph/Data/attack_path_remediation_scripts/management-port-open-to-the-internet.ps1' $result.Status | Should -Be 'Completed' $result.DurationSeconds | Should -BeGreaterOrEqual 0 } It 'Does not execute remediation script when -WhatIf is specified' { $filePath = Join-Path $TestDrive 'attack-path-remediation-whatif.txt' $attackPath = InModuleScope Devolutions.CIEM -Parameters @{ filePath = $filePath } { param($filePath) $item = [CIEMAttackPath]::new() $item.PatternId = 'whatif-test' $escapedPath = $filePath.Replace("'", "''") $item.RemediationScript = "Set-Content -Path '$escapedPath' -Value 'should-not-run'" $item } $result = @($attackPath | Invoke-CIEMAttackPathRemediation -WhatIf) $filePath | Should -Not -Exist $result | Should -HaveCount 0 } It 'Throws when attack path has no remediation script' { $attackPath = InModuleScope Devolutions.CIEM { $item = [CIEMAttackPath]::new() $item.PatternId = 'missing-script' $item } { $attackPath | Invoke-CIEMAttackPathRemediation -Confirm:$false } | Should -Throw '*RemediationScript is empty*' } } } |