modules/Azure/Discovery/Tests/Unit/BuildCIEMEntraTransitiveMembership.Tests.ps1
|
BeforeAll { . (Join-Path $PSScriptRoot 'TestSetup.ps1') Remove-Module Devolutions.CIEM -Force -ErrorAction SilentlyContinue Import-Module (Join-Path $PSScriptRoot '..' '..' '..' '..' '..' 'Devolutions.CIEM.psd1') } Describe 'BuildCIEMEntraTransitiveMembership' { BeforeEach { Initialize-DiscoveryTestDatabase Mock -ModuleName Devolutions.CIEM Write-CIEMLog {} } It 'Builds transitive group membership from direct member_of relationships' { InModuleScope Devolutions.CIEM { $relationships = @( [pscustomobject]@{ SourceId = 'user-1'; SourceType = 'user'; TargetId = 'group-a'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'group-a'; SourceType = 'group'; TargetId = 'group-b'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'group-b'; SourceType = 'group'; TargetId = 'group-c'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } ) $results = @(BuildCIEMEntraTransitiveMembership -Relationships $relationships -CollectedAt '2026-01-02T00:00:00Z') $results | Should -HaveCount 6 ($results | Where-Object { $_.SourceId -eq 'user-1' }).TargetId | Sort-Object | Should -Be @('group-a', 'group-b', 'group-c') ($results | Where-Object { $_.SourceId -eq 'group-a' }).TargetId | Sort-Object | Should -Be @('group-b', 'group-c') ($results | Where-Object { $_.SourceId -eq 'group-b' }).TargetId | Should -Be 'group-c' } } It 'Terminates when there is a self-reference cycle' { InModuleScope Devolutions.CIEM { $relationships = @( [pscustomobject]@{ SourceId = 'user-1'; SourceType = 'user'; TargetId = 'group-a'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'group-a'; SourceType = 'group'; TargetId = 'group-a'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } ) $results = @(BuildCIEMEntraTransitiveMembership -Relationships $relationships -CollectedAt '2026-01-02T00:00:00Z') $results | Should -HaveCount 2 ($results | Where-Object { $_.SourceId -eq 'user-1' }).TargetId | Should -Be 'group-a' ($results | Where-Object { $_.SourceId -eq 'group-a' }).TargetId | Should -Be 'group-a' } } It 'Returns an empty set for orphan users' { InModuleScope Devolutions.CIEM { $results = @(BuildCIEMEntraTransitiveMembership -Relationships @() -CollectedAt '2026-01-02T00:00:00Z') $results | Should -HaveCount 0 } } It 'Deduplicates users reachable through two paths' { InModuleScope Devolutions.CIEM { $relationships = @( [pscustomobject]@{ SourceId = 'user-1'; SourceType = 'user'; TargetId = 'group-a'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'user-1'; SourceType = 'user'; TargetId = 'group-b'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'group-a'; SourceType = 'group'; TargetId = 'group-c'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } [pscustomobject]@{ SourceId = 'group-b'; SourceType = 'group'; TargetId = 'group-c'; TargetType = 'group'; Relationship = 'member_of'; CollectedAt = '2026-01-01T00:00:00Z' } ) $results = @(BuildCIEMEntraTransitiveMembership -Relationships $relationships -CollectedAt '2026-01-02T00:00:00Z') ($results | Where-Object { $_.TargetId -eq 'group-c' -and $_.SourceId -eq 'user-1' }) | Should -HaveCount 1 } } } |