Tests/Unit/GetCIEMRequiredPermission.Tests.ps1
|
BeforeAll { Remove-Module Devolutions.CIEM -Force -ErrorAction SilentlyContinue Import-Module (Join-Path $PSScriptRoot '..' '..' 'Devolutions.CIEM.psd1') Mock -ModuleName Devolutions.CIEM Write-CIEMLog {} $script:RemediationPermissionCatalogPath = Join-Path $PSScriptRoot '..' '..' 'modules' 'Devolutions.CIEM.Checks' 'Data' 'remediation-permissions.json' $script:RemediationPermissionCatalog = Get-Content $script:RemediationPermissionCatalogPath -Raw | ConvertFrom-Json -AsHashtable } Describe 'Get-CIEMRequiredPermission' { Context 'when Azure discovery endpoints and remediation templates are available' { BeforeAll { $tokens = @( 'NSG_RULE_DELETE_COMMANDS', 'ROLE_ASSIGNMENT_DELETE_COMMANDS', 'GROUP_MEMBER_REMOVE_COMMANDS' ) $script:ExpectedRemediationGraph = @( foreach ($token in $tokens) { foreach ($permission in @($script:RemediationPermissionCatalog.Azure.RemediationTokens[$token].Graph)) { $permission } } ) | Select-Object -Unique | Sort-Object $script:ExpectedRemediationAzureRoles = @( foreach ($token in $tokens) { foreach ($role in @($script:RemediationPermissionCatalog.Azure.RemediationTokens[$token].AzureRoles)) { $role } } ) | Select-Object -Unique | Sort-Object Mock -ModuleName Devolutions.CIEM Get-CIEMCheck { @() } Mock -ModuleName Devolutions.CIEM GetCIEMAzureProviderApi { @( [pscustomobject]@{ Permissions = [pscustomobject]@{ Graph = @('Directory.Read.All', 'AuditLog.Read.All') AzureRoles = @('Reader') } } ) } Mock -ModuleName Devolutions.CIEM Get-ChildItem { @( [pscustomobject]@{ FullName = '/mock/management-port-open-to-the-internet.ps1' } [pscustomobject]@{ FullName = '/mock/service-principal-holding-owner-role-on-a-subscription.ps1' } [pscustomobject]@{ FullName = '/mock/guest-user-is-a-member-of-a-group-that-holds-a-privileged-role.ps1' } ) } -ParameterFilter { $Path -like '*attack_path_remediation_scripts*' -and $File } Mock -ModuleName Devolutions.CIEM Get-Content { if ($Path -eq '/mock/management-port-open-to-the-internet.ps1') { return @' {{NSG_RULE_DELETE_COMMANDS}} '@ } if ($Path -eq '/mock/service-principal-holding-owner-role-on-a-subscription.ps1') { return @' {{ROLE_ASSIGNMENT_DELETE_COMMANDS}} '@ } if ($Path -eq '/mock/guest-user-is-a-member-of-a-group-that-holds-a-privileged-role.ps1') { return @' {{GROUP_MEMBER_REMOVE_COMMANDS}} '@ } Microsoft.PowerShell.Management\Get-Content -Path $Path -Raw:$Raw } } It 'returns discovery and remediation permissions as separate sections' { $result = Get-CIEMRequiredPermission -Provider Azure $result.Discovery | Should -Not -BeNullOrEmpty $result.Remediation | Should -Not -BeNullOrEmpty } It 'keeps discovery requirements scoped to discovery reads' { $result = Get-CIEMRequiredPermission -Provider Azure $result.Discovery.Graph | Should -Contain 'AuditLog.Read.All' $result.Discovery.Graph | Should -Contain 'Directory.Read.All' $result.Discovery.AzureRoles | Should -Contain 'Reader' $result.Discovery.AzureRoles | Should -Not -Contain 'Network Contributor' $result.Discovery.AzureRoles | Should -Not -Contain 'User Access Administrator' } It 'reports remediation write permissions separately from discovery permissions' { $result = Get-CIEMRequiredPermission -Provider Azure $result.Remediation.Graph | Should -Be $script:ExpectedRemediationGraph $result.Remediation.AzureRoles | Should -Be $script:ExpectedRemediationAzureRoles $result.Remediation.AzureRoles | Should -Not -Contain 'Reader' $result.Remediation.TemplateCount | Should -Be 3 } } } |