Testing/Unit/PowerShell/Providers/AADProvider/Export-Caps.Tests.ps1
|
BeforeAll { $ClassPath = (Join-Path -Path $PSScriptRoot -ChildPath "./../../../../../Modules/Providers/ProviderHelpers/AADConditionalAccessHelper.psm1") Import-Module $ClassPath [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'CapHelper')] $CapHelper = Get-CapTracker } Describe "GetIncludedUsers" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/Users.json") | ConvertFrom-Json } It "returns 'None' when no users are included" { $Cap.Conditions.Users.IncludeUsers += "None" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "None" } It "handles including single users" { $Cap.Conditions.Users.IncludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "1 specific user" } It "handles including multiple users" { $Cap.Conditions.Users.IncludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeUsers += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "2 specific users" } It "handles including single groups" { $Cap.Conditions.Users.IncludeGroups += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "1 specific group" } It "handles including multiple groups" { $Cap.Conditions.Users.IncludeGroups += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeGroups += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "2 specific groups" } It "handles including single roles" { $Cap.Conditions.Users.IncludeRoles += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "1 specific role" } It "handles including multiple roles" { $Cap.Conditions.Users.IncludeRoles += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeRoles += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "2 specific roles" } It "handles including users, groups, and roles simultaneously" { $Cap.Conditions.Users.IncludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeRoles += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeRoles += "caaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeGroups += "daaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.IncludeGroups += "eaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #gitleaks:allow $Cap.Conditions.Users.IncludeGroups += "faaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "1 specific user, 2 specific roles, 3 specific groups" } It "returns 'All' when all users are included" { $Cap.Conditions.Users.IncludeUsers += "all" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "All" } It "handles including single type of external user" { $Cap.Conditions.Users.IncludeGuestsOrExternalUsers.ExternalTenants.MembershipKind = "all" $Cap.Conditions.Users.IncludeGuestsOrExternalUsers.GuestOrExternalUserTypes = "internalGuest" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "Local guest users" } It "handles including all types of guest users" { $Cap.Conditions.Users.IncludeGuestsOrExternalUsers.ExternalTenants.MembershipKind = "all" $Cap.Conditions.Users.IncludeGuestsOrExternalUsers.GuestOrExternalUserTypes = "b2bCollaborationGuest,b2bCollaborationMember,b2bDirectConnectUser,internalGuest,serviceProvider,otherExternalUser" $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap)) -Join ", " $UsersIncluded | Should -Be "B2B collaboration guest users, B2B collaboration member users, B2B direct connect users, Local guest users, Service provider users, Other external users" } It "handles empty input" { $Cap = @{} $UsersIncluded = $($CapHelper.GetIncludedUsers($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $UsersIncluded | Should -Be "" } } Describe "GetExcludedUsers" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/Users.json") | ConvertFrom-Json } It "returns 'None' when no users are included" { $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "None" } It "handles excluding single users" { $Cap.Conditions.Users.ExcludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "1 specific user" } It "handles excluding multiple users" { $Cap.Conditions.Users.ExcludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeUsers += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "2 specific users" } It "handles excluding single groups" { $Cap.Conditions.Users.ExcludeGroups += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "1 specific group" } It "handles excluding multiple groups" { $Cap.Conditions.Users.ExcludeGroups += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeGroups += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "2 specific groups" } It "handles excluding single roles" { $Cap.Conditions.Users.ExcludeRoles += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "1 specific role" } It "handles excluding multiple roles" { $Cap.Conditions.Users.ExcludeRoles += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeRoles += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "2 specific roles" } It "handles excluding users, groups, and roles simultaneously" { $Cap.Conditions.Users.ExcludeUsers += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeRoles += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeRoles += "caaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeGroups += "daaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Users.ExcludeGroups += "eaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #gitleaks:allow $Cap.Conditions.Users.ExcludeGroups += "faaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "1 specific user, 2 specific roles, 3 specific groups" } It "handles excluding all types of external users" { $Cap.Conditions.Users.ExcludeGuestsOrExternalUsers.ExternalTenants.MembershipKind = "all" $Cap.Conditions.Users.ExcludeGuestsOrExternalUsers.GuestOrExternalUserTypes = "b2bCollaborationGuest,b2bCollaborationMember,b2bDirectConnectUser,internalGuest,serviceProvider,otherExternalUser" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "B2B collaboration guest users, B2B collaboration member users, B2B direct connect users, Local guest users, Service provider users, Other external users" } It "handles excluding a single type of external user" { $Cap.Conditions.Users.ExcludeGuestsOrExternalUsers.ExternalTenants.MembershipKind = "all" $Cap.Conditions.Users.ExcludeGuestsOrExternalUsers.GuestOrExternalUserTypes = "serviceProvider" $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap)) -Join ", " $UsersExcluded | Should -Be "Service provider users" } It "handles empty input" { $Cap = @{} $UsersExcluded = $($CapHelper.GetExcludedUsers($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $UsersExcluded | Should -Be "" } } Describe "GetApplications" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/Apps.json") | ConvertFrom-Json } It "handles including all apps" { $Cap.Conditions.Applications.IncludeApplications += "All" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: All" $Apps[2] | Should -Be "Apps excluded: None" } It "handles including/excluding no apps" { $Cap.Conditions.Applications.IncludeApplications += "None" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: None" $Apps[2] | Should -Be "Apps excluded: None" } It "handles including/excluding single specific apps" { $Cap.Conditions.Applications.IncludeApplications += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Applications.ExcludeApplications += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: 1 specific app" $Apps[2] | Should -Be "Apps excluded: 1 specific app" } It "handles including/excluding multiple specific apps" { $Cap.Conditions.Applications.IncludeApplications += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Applications.IncludeApplications += "baaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Applications.IncludeApplications += "caaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Applications.ExcludeApplications += "daaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Cap.Conditions.Applications.ExcludeApplications += "eaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #gitleaks:allow $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: 3 specific apps" $Apps[2] | Should -Be "Apps excluded: 2 specific apps" } It "handles app filter in include mode" { $Cap.Conditions.Applications.ApplicationFilter.Mode = "include" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: custom application filter" $Apps[2] | Should -Be "Apps excluded: None" } It "handles app filter in exclude mode" { $Cap.Conditions.Applications.ApplicationFilter.Mode = "exclude" $Cap.Conditions.Applications.IncludeApplications += "All" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: All" $Apps[2] | Should -Be "Apps excluded: custom application filter" } It "handles including app filter and specific apps" { $Cap.Conditions.Applications.ApplicationFilter.Mode = "include" $Cap.Conditions.Applications.IncludeApplications += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: 1 specific app" $Apps[2] | Should -Be "Apps included: custom application filter" $Apps[3] | Should -Be "Apps excluded: None" } It "handles excluding app filter and specific apps" { $Cap.Conditions.Applications.ApplicationFilter.Mode = "exclude" $Cap.Conditions.Applications.IncludeApplications += "All" $Cap.Conditions.Applications.ExcludeApplications += "aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: apps" $Apps[1] | Should -Be "Apps included: All" $Apps[2] | Should -Be "Apps excluded: 1 specific app" $Apps[3] | Should -Be "Apps excluded: custom application filter" } It "handles registering a device" { $Cap.Conditions.Applications.IncludeUserActions += "urn:user:registerdevice" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: actions" $Apps[1] | Should -Be "User action: Register or join devices" } It "handles registering security info" { $Cap.Conditions.Applications.IncludeUserActions += "urn:user:registersecurityinfo" $Apps = $($CapHelper.GetApplications($Cap)) $Apps[0] | Should -Be "Policy applies to: actions" $Apps[1] | Should -Be "User action: Register security info" } It "handles registering security info" { $Cap.Conditions.Applications.IncludeAuthenticationContextClassReferences += "c1" $Cap.Conditions.Applications.IncludeAuthenticationContextClassReferences += "c3" $Apps = $($CapHelper.GetApplications($Cap)) $Apps | Should -Be "Policy applies to: 2 authentication contexts" } It "handles empty input" { $Cap = @{} $Apps = $($CapHelper.GetApplications($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $Apps | Should -Be "" } } Describe "GetConditions" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/Conditions.json") | ConvertFrom-Json } It "handles user risk levels" { $Cap.Conditions.UserRiskLevels += "high" $Cap.Conditions.UserRiskLevels += "medium" $Cap.Conditions.UserRiskLevels += "low" $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "User risk levels: high, medium, low" } It "handles sign-in risk levels" { $Cap.Conditions.SignInRiskLevels += "low" $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Sign-in risk levels: low" } It "handles including all device platforms" { $Cap.Conditions.Platforms.ExcludePlatforms = @() $Cap.Conditions.Platforms.IncludePlatforms = @("all") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Device platforms included: all" $Conditions[1] | Should -Be "Device platforms excluded: none" } It "handles including/excluding specific device platforms" { $Cap.Conditions.Platforms.ExcludePlatforms = @("iOS", "macOS", "linux") $Cap.Conditions.Platforms.IncludePlatforms = @("android") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Device platforms included: android" $Conditions[1] | Should -Be "Device platforms excluded: iOS, macOS, linux" } It "handles including all locations" { $Cap.Conditions.Locations.ExcludeLocations = @() $Cap.Conditions.Locations.IncludeLocations = @("All") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Locations included: all locations" $Conditions[1] | Should -Be "Locations excluded: none" } It "handles excluding trusted locations" { $Cap.Conditions.Locations.ExcludeLocations = @("AllTrusted") $Cap.Conditions.Locations.IncludeLocations = @("All") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Locations included: all locations" $Conditions[1] | Should -Be "Locations excluded: all trusted locations" } It "handles including/excluding single custom locations" { $Cap.Conditions.Locations.ExcludeLocations = @("00000000-0000-0000-0000-000000000000") $Cap.Conditions.Locations.IncludeLocations = @("10000000-0000-0000-0000-000000000000") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Locations included: 1 specific location" $Conditions[1] | Should -Be "Locations excluded: 1 specific location" } It "handles including/excluding multiple custom locations" { $Cap.Conditions.Locations.ExcludeLocations = @() $Cap.Conditions.Locations.ExcludeLocations += @("00000000-0000-0000-0000-000000000000") $Cap.Conditions.Locations.ExcludeLocations += @("10000000-0000-0000-0000-000000000000") $Cap.Conditions.Locations.ExcludeLocations += @("20000000-0000-0000-0000-000000000000") $Cap.Conditions.Locations.IncludeLocations = @() $Cap.Conditions.Locations.IncludeLocations += @("30000000-0000-0000-0000-000000000000") $Cap.Conditions.Locations.IncludeLocations += @("40000000-0000-0000-0000-000000000000") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Locations included: 2 specific locations" $Conditions[1] | Should -Be "Locations excluded: 3 specific locations" } It "handles including trusted locations" { $Cap.Conditions.Locations.IncludeLocations = @("AllTrusted") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "Locations included: all trusted locations" $Conditions[1] | Should -Be "Locations excluded: none" } It "handles including all client apps" { $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions | Should -Be "Client apps included: all" } It "handles including specific client apps" { $Cap.Conditions.ClientAppTypes = @("exchangeActiveSync", "browser", "mobileAppsAndDesktopClients", "other") $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions | Should -Be "Client apps included: Exchange ActiveSync Clients, Browser, Mobile apps and desktop clients, Other clients" } It "handles custom client app filter in include mode" { $Cap.Conditions.Devices.DeviceFilter.Mode = "include" $Cap.Conditions.Devices.DeviceFilter.Rule = "device.manufacturer -eq 'helloworld'" $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[1] | Should -Be "Custom device filter in include mode active" } It "handles custom client app filter in exclude mode" { $Cap.Conditions.Devices.DeviceFilter.Mode = "exclude" $Cap.Conditions.Devices.DeviceFilter.Rule = "device.manufacturer -eq 'helloworld'" $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[1] | Should -Be "Custom device filter in exclude mode active" } It "handles many conditions simultaneously" { $Cap.Conditions.UserRiskLevels += "low" $Cap.Conditions.SignInRiskLevels += "high" $Cap.Conditions.Platforms.ExcludePlatforms = @("android", "iOS", "macOS", "linux") $Cap.Conditions.Platforms.IncludePlatforms = @("all") $Cap.Conditions.Locations.IncludeLocations = @("AllTrusted") $Cap.Conditions.Locations.ExcludeLocations = @() $Cap.Conditions.ClientAppTypes = @("exchangeActiveSync") $Cap.Conditions.Devices.DeviceFilter.Mode = "exclude" $Cap.Conditions.Devices.DeviceFilter.Rule = "device.manufacturer -eq 'helloworld'" $Conditions = $($CapHelper.GetConditions($Cap)) $Conditions[0] | Should -Be "User risk levels: low" $Conditions[1] | Should -Be "Sign-in risk levels: high" $Conditions[2] | Should -Be "Device platforms included: all" $Conditions[3] | Should -Be "Device platforms excluded: android, iOS, macOS, linux" $Conditions[4] | Should -Be "Locations included: all trusted locations" $Conditions[5] | Should -Be "Locations excluded: none" $Conditions[6] | Should -Be "Client apps included: Exchange ActiveSync Clients" $Conditions[7] | Should -Be "Custom device filter in exclude mode active" } It "handles empty input" { $Cap = @{} $Conditions = $($CapHelper.GetConditions($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $Conditions | Should -Be "" } } Describe "GetAccessControls" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/AccessControls.json") | ConvertFrom-Json } It "handles blocking access" { $Cap.GrantControls.BuiltInControls = @("block") $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Block access" } It "handles requiring single control" { $Cap.GrantControls.BuiltInControls = @("mfa") $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require multifactor authentication" } It "handles requiring terms of use" { $Cap.GrantControls.TermsOfUse = @("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require terms of use" } It "handles requiring multiple controls in AND mode" { $Cap.GrantControls.BuiltInControls = @("mfa", "compliantDevice", "domainJoinedDevice", "approvedApplication", "compliantApplication", "passwordChange") $Cap.GrantControls.Operator = "AND" $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require multifactor authentication, device to be marked compliant, Hybrid Azure AD joined device, approved client app, app protection policy, AND password change" } It "handles requiring multiple controls in OR mode" { $Cap.GrantControls.BuiltInControls = @("mfa", "compliantDevice", "domainJoinedDevice", "approvedApplication", "compliantApplication", "passwordChange") $Cap.GrantControls.Operator = "OR" $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require multifactor authentication, device to be marked compliant, Hybrid Azure AD joined device, approved client app, app protection policy, OR password change" } It "handles using authentication strength (phishing resistant MFA)" { $Cap.GrantControls.AuthenticationStrength.DisplayName = "Phishing resistant MFA" $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require authentication strength (Phishing resistant MFA)" } It "handles using both authentication strength and a traditional control" { $Cap.GrantControls.AuthenticationStrength.DisplayName = "Multi-factor authentication" $Cap.GrantControls.BuiltInControls = @("passwordChange") $Cap.GrantControls.Operator = "AND" $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "Allow access but require password change, AND authentication strength (Multi-factor authentication)" } It "handles using no access controls" { $Cap.GrantControls.BuiltInControls = $null $Controls = $($CapHelper.GetAccessControls($Cap)) $Controls | Should -Be "None" } It "handles empty input" { $Cap = @{} $Controls = $($CapHelper.GetAccessControls($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $Controls | Should -Be "" } } Describe "GetSessionControls" { BeforeEach { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Cap')] $Cap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/SessionControls.json") | ConvertFrom-Json } It "handles using no session controls" { $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "None" } It "handles using app enforced restrictions" { $Cap.SessionControls.ApplicationEnforcedRestrictions.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Use app enforced restrictions" } It "handles using conditional access app control with custom policy" { $Cap.SessionControls.CloudAppSecurity.CloudAppSecurityType = "mcasConfigured" $Cap.SessionControls.CloudAppSecurity.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Use Conditional Access App Control (Use custom policy)" } It "handles using conditional access app control in monitor mode" { $Cap.SessionControls.CloudAppSecurity.CloudAppSecurityType = "monitorOnly" $Cap.SessionControls.CloudAppSecurity.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Use Conditional Access App Control (Monitor only)" } It "handles using conditional access app control in block mode" { $Cap.SessionControls.CloudAppSecurity.CloudAppSecurityType = "blockDownloads" $Cap.SessionControls.CloudAppSecurity.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Use Conditional Access App Control (Block downloads)" } It "handles using sign-in frequency every time" { $Cap.SessionControls.SignInFrequency.FrequencyInterval = "everyTime" $Cap.SessionControls.SignInFrequency.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Sign-in frequency (every time)" } It "handles using sign-in frequency time based" { $Cap.SessionControls.SignInFrequency.FrequencyInterval = "timeBased" $Cap.SessionControls.SignInFrequency.Type = "days" $Cap.SessionControls.SignInFrequency.Value = 10 $Cap.SessionControls.SignInFrequency.IsEnabled = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Sign-in frequency (every 10 days)" } It "handles using persistent browser session" { $Cap.SessionControls.PersistentBrowser.IsEnabled = $true $Cap.SessionControls.PersistentBrowser.Mode = "never" $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Persistent browser session (never persistent)" } It "handles using customized continuous access evaluation" { $Cap.SessionControls.ContinuousAccessEvaluation.Mode = "disabled" $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Customize continuous access evaluation" } It "handles disabling resilience defaults" { $Cap.SessionControls.DisableResilienceDefaults = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls | Should -Be "Disable resilience defaults" } It "handles multiple controls simultaneously" { $Cap.SessionControls.PersistentBrowser.IsEnabled = $true $Cap.SessionControls.PersistentBrowser.Mode = "never" $Cap.SessionControls.DisableResilienceDefaults = $true $Controls = $($CapHelper.GetSessionControls($Cap)) $Controls[0] | Should -Be "Persistent browser session (never persistent)" $Controls[1] | Should -Be "Disable resilience defaults" } It "handles empty input" { $Cap = @{} $Controls = $($CapHelper.GetSessionControls($Cap) 3>$null) -Join ", " # 3>$null to surpress the warning # message as it is expected in this case $Controls | Should -Be "" } } Describe "ExportCapPolicies Sorting" { BeforeEach { # Load base CAP structure from existing snippets [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'BaseCap')] $BaseCap = Get-Content (Join-Path -Path $PSScriptRoot -ChildPath "./CapSnippets/Users.json") | ConvertFrom-Json # Create test policies with different states and names for sorting [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Caps')] $Caps = @() # Create "Off" policy (should be last) $OffPolicy = $BaseCap.PSObject.Copy() $OffPolicy | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "Z Policy" $OffPolicy | Add-Member -MemberType NoteProperty -Name "State" -Value "disabled" $Caps += $OffPolicy # Create "On" policy (should be first) $OnPolicy = $BaseCap.PSObject.Copy() $OnPolicy | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "A Policy" $OnPolicy | Add-Member -MemberType NoteProperty -Name "State" -Value "enabled" $Caps += $OnPolicy # Create "On" second policy (should be first) $OnPolicy = $BaseCap.PSObject.Copy() $OnPolicy | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "A Policy 2" $OnPolicy | Add-Member -MemberType NoteProperty -Name "State" -Value "enabled" $Caps += $OnPolicy # Create "Report-only" policy (should be middle) $ReportPolicy = $BaseCap.PSObject.Copy() $ReportPolicy | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "B Policy" $ReportPolicy | Add-Member -MemberType NoteProperty -Name "State" -Value "enabledForReportingButNotEnforced" $Caps += $ReportPolicy } It "sorts policies by State first (On, Report-only, Off), then by Name alphabetically" { # Suppress warnings since we're using incomplete CAP structures for testing $Result = $CapHelper.ExportCapPolicies($Caps) 3>$null $ParsedResult = ConvertFrom-Json $Result # Verify the order: "A Policy" (On) -> "A Policy 2" (On) -> "B Policy" (Report-only) -> "Z Policy" (Off) $ParsedResult[0].Name | Should -Be "A Policy" $ParsedResult[0].State | Should -Be "On" $ParsedResult[1].Name | Should -Be "A Policy 2" $ParsedResult[1].State | Should -Be "On" $ParsedResult[2].Name | Should -Be "B Policy" $ParsedResult[2].State | Should -Be "Report-only" $ParsedResult[3].Name | Should -Be "Z Policy" $ParsedResult[3].State | Should -Be "Off" } } |