From 0f3854ed621514f4300e37ee95dd15fe86a2155c Mon Sep 17 00:00:00 2001 From: Michael Barmettler <99532854+mibarm@users.noreply.github.com> Date: Mon, 22 Jan 2024 08:00:10 +0100 Subject: [PATCH] add test and check params --- .../MSFT_AADConditionalAccessPolicy.psm1 | 743 +++++++++--------- ...65DSC.AADConditionalAccessPolicy.Tests.ps1 | 118 +++ 2 files changed, 486 insertions(+), 375 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 index 7dbfcd0e43..7f3e7c076f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 @@ -954,22 +954,14 @@ function Set-TargetResource } #create and provision Application Condition object Write-Verbose -Message 'Set-Targetresource: create Application Condition object' - if ($IncludeApplications) + if ($currentParameters.ContainsKey("IncludeApplications")) { $conditions.Applications.Add('IncludeApplications', $IncludeApplications) } - else - { - $conditions.Applications.Add('IncludeApplications', $currentPolicy.IncludeApplications) - } if ($currentParameters.ContainsKey("ExcludeApplications")) { $conditions.Applications.Add('ExcludeApplications', $ExcludeApplications) } - else - { - $conditions.Applications.Add('ExcludeApplications', $currentPolicy.ExcludeApplications) - } if ($ApplicationsFilter -and $ApplicationsFilterMode) { $appFilterValue = @{ @@ -978,19 +970,10 @@ function Set-TargetResource } $conditions.Applications.Add("ApplicationFilter", $appFilterValue) } - else - { - $conditions.Applications.Add("ApplicationFilter", $currentPolicy.ApplicationsFilter) - } - if ($IncludeUserActions) { $conditions.Applications.Add('IncludeUserActions', $IncludeUserActions) } - else - { - $conditions.Applications.Add('IncludeUserActions', $currentPolicy.IncludeUserActions) - } if ($AuthenticationContexts) { # Retrieve the class reference based on display name. @@ -1009,21 +992,108 @@ function Set-TargetResource #create and provision User Condition object Write-Verbose -Message 'Set-Targetresource: process includeusers' - if (!$currentParameters.ContainsKey('IncludeUsers') -and $null -ne $currentPolicy.IncludeUsers) { - $IncludeUsers = $currentPolicy.IncludeUsers + if ($currentParameters.ContainsKey('IncludeUsers')) + { + $conditions.Users.Add('IncludeUsers', @()) + foreach ($includeuser in $IncludeUsers) + { + #translate user UPNs to GUID, except id value is GuestsOrExternalUsers, None or All + if ($includeuser) + { + if ($includeuser -notin 'GuestsOrExternalUsers', 'All', 'None') + { + $userguid = $null + try + { + $userguid = (Get-MgUser -UserId $includeuser).Id + } + catch + { + New-M365DSCLogEntry -Message 'Error updating data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + if ($null -eq $userguid) + { + $message = "Couldn't find user $includeuser , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Users.IncludeUsers += $userguid + } + } + else + { + $conditions.Users.IncludeUsers += $includeuser + } + } + } + } + + Write-Verbose -Message 'Set-Targetresource: process excludeusers' + if ($currentParameters.ContainsKey('ExcludeUsers')) + { + $conditions.Users.Add('ExcludeUsers', @()) + foreach ($excludeuser in $ExcludeUsers) + { + #translate user UPNs to GUID, except id value is GuestsOrExternalUsers, None or All + if ($excludeuser) + { + if ($excludeuser -notin 'GuestsOrExternalUsers', 'All', 'None') + { + $userguid = $null + try + { + $userguid = (Get-MgUser -UserId $excludeuser).Id + } + catch + { + New-M365DSCLogEntry -Message 'Error updating data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + if ($null -eq $userguid) + { + $message = "Couldn't find user $excludeuser , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Users.ExcludeUsers += $userguid + } + } + else + { + $conditions.Users.ExcludeUsers += $excludeuser + } + } + } } - $conditions.Users.Add('IncludeUsers', @()) - foreach ($includeuser in $IncludeUsers) + + Write-Verbose -Message 'Set-Targetresource: process includegroups' + if ($currentParameters.ContainsKey('IncludeGroups')) { - #translate user UPNs to GUID, except id value is GuestsOrExternalUsers, None or All - if ($includeuser) + $conditions.Users.Add('IncludeGroups', @()) + foreach ($includegroup in $IncludeGroups) { - if ($includeuser -notin 'GuestsOrExternalUsers', 'All', 'None') + #translate user Group names to GUID + if ($includegroup) { - $userguid = $null + $GroupLookup = $null try { - $userguid = (Get-MgUser -UserId $includeuser).Id + $GroupLookup = Get-MgGroup -Filter "DisplayName eq '$includegroup'" } catch { @@ -1033,9 +1103,17 @@ function Set-TargetResource -TenantId $TenantId ` -Credential $Credential } - if ($null -eq $userguid) + if ($GroupLookup.Length -gt 1) { - $message = "Couldn't find user $includeuser , couldn't add to policy $DisplayName" + $message = "Duplicate group found with displayname $includegroup , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + elseif ($null -eq $GroupLookup) + { + $message = "Couldn't find group $includegroup , couldn't add to policy $DisplayName" New-M365DSCLogEntry -Message $message ` -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` @@ -1043,32 +1121,26 @@ function Set-TargetResource } else { - $conditions.Users.IncludeUsers += $userguid + Write-Verbose -Message 'adding group to includegroups' + $conditions.Users.IncludeGroups += $GroupLookup.Id } } - else - { - $conditions.Users.IncludeUsers += $includeuser - } } } - Write-Verbose -Message 'Set-Targetresource: process excludeusers' - if (!$currentParameters.ContainsKey('ExcludeUsers') -and $null -ne $currentPolicy.ExcludeUsers) { - $ExcludeUsers = $currentPolicy.ExcludeUsers - } - $conditions.Users.Add('ExcludeUsers', @()) - foreach ($excludeuser in $ExcludeUsers) + Write-Verbose -Message 'Set-Targetresource: process excludegroups' + if ($currentParameters.ContainsKey('ExcludeGroups')) { - #translate user UPNs to GUID, except id value is GuestsOrExternalUsers, None or All - if ($excludeuser) + $conditions.Users.Add('ExcludeGroups', @()) + foreach ($ExcludeGroup in $ExcludeGroups) { - if ($excludeuser -notin 'GuestsOrExternalUsers', 'All', 'None') + #translate user Group names to GUID + if ($ExcludeGroup) { - $userguid = $null + $GroupLookup = $null try { - $userguid = (Get-MgUser -UserId $excludeuser).Id + $GroupLookup = Get-MgGroup -Filter "DisplayName eq '$ExcludeGroup'" } catch { @@ -1078,9 +1150,17 @@ function Set-TargetResource -TenantId $TenantId ` -Credential $Credential } - if ($null -eq $userguid) + if ($GroupLookup.Length -gt 1) + { + $message = "Duplicate group found with displayname $ExcludeGroup , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + elseif ($null -eq $GroupLookup) { - $message = "Couldn't find user $excludeuser , couldn't add to policy $DisplayName" + $message = "Couldn't find group $ExcludeGroup , couldn't add to policy $DisplayName" New-M365DSCLogEntry -Message $message ` -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` @@ -1088,387 +1168,283 @@ function Set-TargetResource } else { - $conditions.Users.ExcludeUsers += $userguid + Write-Verbose -Message 'adding group to ExcludeGroups' + $conditions.Users.ExcludeGroups += $GroupLookup.Id } } - else - { - $conditions.Users.ExcludeUsers += $excludeuser - } } } - Write-Verbose -Message 'Set-Targetresource: process includegroups' - if (!$currentParameters.ContainsKey('IncludeGroups') -and $null -ne $currentPolicy.IncludeGroups) { - $IncludeGroups = $currentPolicy.IncludeGroups - } - $conditions.Users.Add('IncludeGroups', @()) - foreach ($includegroup in $IncludeGroups) + + Write-Verbose -Message 'Set-Targetresource: process includeroles' + if ($currentParameters.ContainsKey('IncludeRoles')) { - #translate user Group names to GUID - if ($includegroup) + $conditions.Users.Add('IncludeRoles', @()) + if ($IncludeRoles) { - $GroupLookup = $null - try - { - $GroupLookup = Get-MgGroup -Filter "DisplayName eq '$includegroup'" - } - catch - { - New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - if ($GroupLookup.Length -gt 1) + #translate role names to template guid if defined + $rolelookup = @{} + foreach ($role in Get-MgBetaDirectoryRoleTemplate) { - $message = "Duplicate group found with displayname $includegroup , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + $rolelookup[$role.DisplayName] = $role.Id } - elseif ($null -eq $GroupLookup) + foreach ($IncludeRole in $IncludeRoles) { - $message = "Couldn't find group $includegroup , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - else - { - Write-Verbose -Message 'adding group to includegroups' - $conditions.Users.IncludeGroups += $GroupLookup.Id + if ($IncludeRole) + { + if ($null -eq $rolelookup[$IncludeRole]) + { + $message = "Couldn't find role $IncludeRole , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Users.IncludeRoles += $rolelookup[$IncludeRole] + } + } } } } - Write-Verbose -Message 'Set-Targetresource: process excludegroups' - if (!$currentParameters.ContainsKey('ExcludeGroups') -and $null -ne $currentPolicy.ExcludeGroups) { - $ExcludeGroups = $currentPolicy.ExcludeGroups - } - $conditions.Users.Add('ExcludeGroups', @()) - foreach ($ExcludeGroup in $ExcludeGroups) + Write-Verbose -Message 'Set-Targetresource: process excluderoles' + if ($currentParameters.ContainsKey('ExcludeRoles')) { - #translate user Group names to GUID - if ($ExcludeGroup) + $conditions.Users.Add('ExcludeRoles', @()) + if ($ExcludeRoles) { - $GroupLookup = $null - try + #translate role names to template guid if defined + $rolelookup = @{} + foreach ($role in Get-MgBetaDirectoryRoleTemplate) { - $GroupLookup = Get-MgGroup -Filter "DisplayName eq '$ExcludeGroup'" + $rolelookup[$role.DisplayName] = $role.Id } - catch + foreach ($ExcludeRole in $ExcludeRoles) { - New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + if ($ExcludeRole) + { + if ($null -eq $rolelookup[$ExcludeRole]) + { + $message = "Couldn't find role $ExcludeRole , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Users.ExcludeRoles += $rolelookup[$ExcludeRole] + } + } } - if ($GroupLookup.Length -gt 1) + } + } + + Write-Verbose -Message 'Set-Targetresource: process includeGuestOrExternalUser' + If ($currentParameters.ContainsKey('IncludeGuestOrExternalUserTypes')) + { + if ($IncludeGuestOrExternalUserTypes.Count -ne 0) + { + $includeGuestsOrExternalUsers = @{} + [string]$IncludeGuestOrExternalUserTypes = $IncludeGuestOrExternalUserTypes -join ',' + $includeGuestsOrExternalUsers.Add('guestOrExternalUserTypes', $IncludeGuestOrExternalUserTypes) + $externalTenants = @{} + if ($IncludeExternalTenantsMembershipKind -eq 'All') { - $message = "Duplicate group found with displayname $ExcludeGroup , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessAllExternalTenants') } - elseif ($null -eq $GroupLookup) + elseif ($IncludeExternalTenantsMembershipKind -eq 'enumerated') { - $message = "Couldn't find group $ExcludeGroup , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessEnumeratedExternalTenants') } - else + $externalTenants.Add('membershipKind', $IncludeExternalTenantsMembershipKind) + if ($IncludeExternalTenantsMembers) { - Write-Verbose -Message 'adding group to ExcludeGroups' - $conditions.Users.ExcludeGroups += $GroupLookup.Id + $externalTenants.Add('members', $IncludeExternalTenantsMembers) } + $includeGuestsOrExternalUsers.Add('externalTenants', $externalTenants) + $conditions.Users.Add('includeGuestsOrExternalUsers', $includeGuestsOrExternalUsers) } } - Write-Verbose -Message 'Set-Targetresource: process includeroles' - if (!$currentParameters.ContainsKey('IncludeRoles') -and $null -ne $currentPolicy.IncludeRoles) { - $IncludeRoles = $currentPolicy.IncludeRoles - } - $conditions.Users.Add('IncludeRoles', @()) - if ($IncludeRoles) + Write-Verbose -Message 'Set-Targetresource: process excludeGuestsOrExternalUsers' + If ($currentParameters.ContainsKey('ExcludeGuestOrExternalUserTypes')) { - #translate role names to template guid if defined - $rolelookup = @{} - foreach ($role in Get-MgBetaDirectoryRoleTemplate) - { - $rolelookup[$role.DisplayName] = $role.Id - } - foreach ($IncludeRole in $IncludeRoles) + if ($ExcludeGuestOrExternalUserTypes.Count -ne 0) { - if ($IncludeRole) + $excludeGuestsOrExternalUsers = @{} + [string]$ExcludeGuestOrExternalUserTypes = $ExcludeGuestOrExternalUserTypes -join ',' + $excludeGuestsOrExternalUsers.Add('guestOrExternalUserTypes', $ExcludeGuestOrExternalUserTypes) + $externalTenants = @{} + if ($ExcludeExternalTenantsMembershipKind -eq 'All') { - if ($null -eq $rolelookup[$IncludeRole]) - { - $message = "Couldn't find role $IncludeRole , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - else - { - $conditions.Users.IncludeRoles += $rolelookup[$IncludeRole] - } + $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessAllExternalTenants') } - } - } - - Write-Verbose -Message 'Set-Targetresource: process excluderoles' - if (!$currentParameters.ContainsKey('ExcludeRoles') -and $null -ne $currentPolicy.ExcludeRoles) { - $ExcludeRoles = $currentPolicy.ExcludeRoles - } - $conditions.Users.Add('ExcludeRoles', @()) - if ($ExcludeRoles) - { - #translate role names to template guid if defined - $rolelookup = @{} - foreach ($role in Get-MgBetaDirectoryRoleTemplate) - { - $rolelookup[$role.DisplayName] = $role.Id - } - foreach ($ExcludeRole in $ExcludeRoles) - { - if ($ExcludeRole) + elseif ($ExcludeExternalTenantsMembershipKind -eq 'enumerated') { - if ($null -eq $rolelookup[$ExcludeRole]) - { - $message = "Couldn't find role $ExcludeRole , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - else - { - $conditions.Users.ExcludeRoles += $rolelookup[$ExcludeRole] - } - + $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessEnumeratedExternalTenants') } + $externalTenants.Add('membershipKind', $ExcludeExternalTenantsMembershipKind) + if ($ExcludeExternalTenantsMembers) + { + $externalTenants.Add('members', $ExcludeExternalTenantsMembers) + } + $excludeGuestsOrExternalUsers.Add('externalTenants', $externalTenants) + $conditions.Users.Add('excludeGuestsOrExternalUsers', $excludeGuestsOrExternalUsers) } } - Write-Verbose -Message 'Set-Targetresource: process includeGuestOrExternalUser' - If (!$currentParameters.ContainsKey('IncludeGuestOrExternalUserTypes') -and $null -ne $currentPolicy.IncludeGuestOrExternalUserTypes) { - $IncludeGuestOrExternalUserTypes = $currentPolicy.IncludeGuestOrExternalUserTypes - } - if ($IncludeGuestOrExternalUserTypes.Count -ne 0) - { - $includeGuestsOrExternalUsers = @{} - [string]$IncludeGuestOrExternalUserTypes = $IncludeGuestOrExternalUserTypes -join ',' - $includeGuestsOrExternalUsers.Add('guestOrExternalUserTypes', $IncludeGuestOrExternalUserTypes) - $externalTenants = @{} - if ($IncludeExternalTenantsMembershipKind -eq 'All') - { - $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessAllExternalTenants') - } - elseif ($IncludeExternalTenantsMembershipKind -eq 'enumerated') - { - $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessEnumeratedExternalTenants') - } - $externalTenants.Add('membershipKind', $IncludeExternalTenantsMembershipKind) - if ($IncludeExternalTenantsMembers) - { - $externalTenants.Add('members', $IncludeExternalTenantsMembers) - } - $includeGuestsOrExternalUsers.Add('externalTenants', $externalTenants) - $conditions.Users.Add('includeGuestsOrExternalUsers', $includeGuestsOrExternalUsers) - } - Write-Verbose -Message 'Set-Targetresource: process excludeGuestsOrExternalUsers' - If (!$currentParameters.ContainsKey('ExcludeGuestOrExternalUserTypes') -and $null -ne $currentPolicy.ExcludeGuestOrExternalUserTypes) { - $ExcludeGuestOrExternalUserTypes = $currentPolicy.ExcludeGuestOrExternalUserTypes - } - if ($ExcludeGuestOrExternalUserTypes.Count -ne 0) - { - $excludeGuestsOrExternalUsers = @{} - [string]$ExcludeGuestOrExternalUserTypes = $ExcludeGuestOrExternalUserTypes -join ',' - $excludeGuestsOrExternalUsers.Add('guestOrExternalUserTypes', $ExcludeGuestOrExternalUserTypes) - $externalTenants = @{} - if ($ExcludeExternalTenantsMembershipKind -eq 'All') - { - $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessAllExternalTenants') - } - elseif ($ExcludeExternalTenantsMembershipKind -eq 'enumerated') - { - $externalTenants.Add('@odata.type', '#microsoft.graph.conditionalAccessEnumeratedExternalTenants') - } - $externalTenants.Add('membershipKind', $ExcludeExternalTenantsMembershipKind) - if ($ExcludeExternalTenantsMembers) - { - $externalTenants.Add('members', $ExcludeExternalTenantsMembers) - } - $excludeGuestsOrExternalUsers.Add('externalTenants', $externalTenants) - $conditions.Users.Add('excludeGuestsOrExternalUsers', $excludeGuestsOrExternalUsers) - } + Write-Verbose -Message 'Set-Targetresource: process platform condition' - if (!$currentParameters.ContainsKey('IncludePlatforms') -and $null -ne $currentPolicy.IncludePlatforms) - { - $IncludePlatforms = $currentPolicy.IncludePlatforms - } - if (!$currentParameters.ContainsKey('ExcludePlatforms') -and $null -ne $currentPolicy.ExcludePlatforms) - { - $ExcludePlatforms = $currentPolicy.ExcludePlatforms - } - if ($IncludePlatforms -or $ExcludePlatforms) + if ($currentParameters.ContainsKey('IncludePlatforms') -or $currentParameters.ContainsKey('ExcludePlatforms')) { - #create and provision Platform condition object if used - if (-not $conditions.Contains('Platforms')) - { - $conditions.Add('Platforms', @{ - ExcludePlatforms = @() - IncludePlatforms = @() - }) - } - else - { - $conditions.Platforms.Add('ExcludePlatforms', @()) - $conditions.Platforms.Add('IncludePlatforms', @()) - } - Write-Verbose -Message "Set-Targetresource: IncludePlatforms: $IncludePlatforms" - if (([Array]$IncludePlatforms).Length -eq 0) + if ($IncludePlatforms -or $ExcludePlatforms) { - $conditions.Platforms.IncludePlatforms = @('all') + #create and provision Platform condition object if used + if (-not $conditions.Contains('Platforms')) + { + $conditions.Add('Platforms', @{ + ExcludePlatforms = @() + IncludePlatforms = @() + }) + } + else + { + $conditions.Platforms.Add('ExcludePlatforms', @()) + $conditions.Platforms.Add('IncludePlatforms', @()) + } + Write-Verbose -Message "Set-Targetresource: IncludePlatforms: $IncludePlatforms" + if (([Array]$IncludePlatforms).Length -eq 0) + { + $conditions.Platforms.IncludePlatforms = @('all') + } + else + { + $conditions.Platforms.IncludePlatforms = @() + $IncludePlatforms + } + #no translation or conversion needed + Write-Verbose -Message "Set-Targetresource: ExcludePlatforms: $ExcludePlatforms" + $conditions.Platforms.ExcludePlatforms = @() + $ExcludePlatforms + #no translation or conversion needed } else { - $conditions.Platforms.IncludePlatforms = @() + $IncludePlatforms + Write-Verbose -Message 'Set-Targetresource: setting platform condition to null' + $conditions.Platforms = $null } - #no translation or conversion needed - Write-Verbose -Message "Set-Targetresource: ExcludePlatforms: $ExcludePlatforms" - $conditions.Platforms.ExcludePlatforms = @() + $ExcludePlatforms - #no translation or conversion needed - } - else - { - Write-Verbose -Message 'Set-Targetresource: setting platform condition to null' - $conditions.Platforms = $null } + Write-Verbose -Message 'Set-Targetresource: process include and exclude locations' - if (!$currentParameters.ContainsKey('IncludeLocations') -and $null -ne $currentPolicy.IncludeLocations) { - $IncludeLocations = $currentPolicy.IncludeLocations - } - if (!$currentParameters.ContainsKey('ExcludeLocations') -and $null -ne $currentPolicy.ExcludeLocations) { - $ExcludeLocations = $currentPolicy.ExcludeLocations - } - if ($IncludeLocations -or $ExcludeLocations) + if ($currentParameters.ContainsKey('IncludeLocations') -or $currentParameters.ContainsKey('ExcludeLocations')) { - $conditions.Add('Locations', @{ - ExcludeLocations = @() - IncludeLocations = @() - }) - $conditions.Locations.IncludeLocations = @() - $conditions.Locations.ExcludeLocations = @() - Write-Verbose -Message 'Set-Targetresource: locations specified' - #create and provision Location condition object if used, translate Location names to guid - $LocationLookup = @{} - foreach ($Location in Get-MgBetaIdentityConditionalAccessNamedLocation) - { - $LocationLookup[$Location.DisplayName] = $Location.Id - } - foreach ($IncludeLocation in $IncludeLocations) + if ($IncludeLocations -or $ExcludeLocations) { - if ($IncludeLocation) + $conditions.Add('Locations', @{ + ExcludeLocations = @() + IncludeLocations = @() + }) + $conditions.Locations.IncludeLocations = @() + $conditions.Locations.ExcludeLocations = @() + Write-Verbose -Message 'Set-Targetresource: locations specified' + #create and provision Location condition object if used, translate Location names to guid + $LocationLookup = @{} + foreach ($Location in Get-MgBetaIdentityConditionalAccessNamedLocation) { - if ($IncludeLocation -in 'All', 'AllTrusted') - { - $conditions.Locations.IncludeLocations += $IncludeLocation - } - elseif ($IncludeLocation -eq 'Multifactor authentication trusted IPs') - { - $conditions.Locations.IncludeLocations += '00000000-0000-0000-0000-000000000000' - } - elseif ($null -eq $LocationLookup[$IncludeLocation]) - { - $message = "Couldn't find Location $IncludeLocation , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - else - { - $conditions.Locations.IncludeLocations += $LocationLookup[$IncludeLocation] - } + $LocationLookup[$Location.DisplayName] = $Location.Id } - } - foreach ($ExcludeLocation in $ExcludeLocations) - { - if ($ExcludeLocation) + foreach ($IncludeLocation in $IncludeLocations) { - if ($ExcludeLocation -eq 'All' -or $ExcludeLocation -eq 'AllTrusted') - { - $conditions.Locations.ExcludeLocations += $ExcludeLocation - } - elseif ($ExcludeLocation -eq 'Multifactor authentication trusted IPs') + if ($IncludeLocation) { - $conditions.Locations.ExcludeLocations += '00000000-0000-0000-0000-000000000000' - } - elseif ($null -eq $LocationLookup[$ExcludeLocation]) - { - $message = "Couldn't find Location $ExcludeLocation , couldn't add to policy $DisplayName" - New-M365DSCLogEntry -Message $message ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + if ($IncludeLocation -in 'All', 'AllTrusted') + { + $conditions.Locations.IncludeLocations += $IncludeLocation + } + elseif ($IncludeLocation -eq 'Multifactor authentication trusted IPs') + { + $conditions.Locations.IncludeLocations += '00000000-0000-0000-0000-000000000000' + } + elseif ($null -eq $LocationLookup[$IncludeLocation]) + { + $message = "Couldn't find Location $IncludeLocation , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Locations.IncludeLocations += $LocationLookup[$IncludeLocation] + } } - else + } + foreach ($ExcludeLocation in $ExcludeLocations) + { + if ($ExcludeLocation) { - $conditions.Locations.ExcludeLocations += $LocationLookup[$ExcludeLocation] + if ($ExcludeLocation -eq 'All' -or $ExcludeLocation -eq 'AllTrusted') + { + $conditions.Locations.ExcludeLocations += $ExcludeLocation + } + elseif ($ExcludeLocation -eq 'Multifactor authentication trusted IPs') + { + $conditions.Locations.ExcludeLocations += '00000000-0000-0000-0000-000000000000' + } + elseif ($null -eq $LocationLookup[$ExcludeLocation]) + { + $message = "Couldn't find Location $ExcludeLocation , couldn't add to policy $DisplayName" + New-M365DSCLogEntry -Message $message ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + else + { + $conditions.Locations.ExcludeLocations += $LocationLookup[$ExcludeLocation] + } } } } } Write-Verbose -Message 'Set-Targetresource: process device filter' - if (!$currentParameters.ContainsKey('DeviceFilterMode') -and $null -ne $currentPolicy.DeviceFilterMode) { - $DeviceFilterMode = $currentPolicy.DeviceFilterMode - } - if (!$currentParameters.ContainsKey('DeviceFilterRule') -and $null -ne $currentPolicy.DeviceFilterRule) { - $DeviceFilterRule = $currentPolicy.DeviceFilterRule - } - if ($DeviceFilterMode -and $DeviceFilterRule) + if ($currentParameters.ContainsKey('DeviceFilterMode') -and $currentParameters.ContainsKey('DeviceFilterRule')) { - if (-not $conditions.Contains('Devices')) + if ($DeviceFilterMode -and $DeviceFilterRule) { - $conditions.Add('Devices', @{}) - $conditions.Devices.Add('DeviceFilter', @{}) - $conditions.Devices.DeviceFilter.Add('Mode', $DeviceFilterMode) - $conditions.Devices.DeviceFilter.Add('Rule', $DeviceFilterRule) - } - else - { - if (-not $conditions.Devices.Contains('DeviceFilter')) + if (-not $conditions.Contains('Devices')) { + $conditions.Add('Devices', @{}) $conditions.Devices.Add('DeviceFilter', @{}) $conditions.Devices.DeviceFilter.Add('Mode', $DeviceFilterMode) $conditions.Devices.DeviceFilter.Add('Rule', $DeviceFilterRule) } else { - if (-not $conditions.Devices.DeviceFilter.Contains('Mode')) + if (-not $conditions.Devices.Contains('DeviceFilter')) { + $conditions.Devices.Add('DeviceFilter', @{}) $conditions.Devices.DeviceFilter.Add('Mode', $DeviceFilterMode) - } - else - { - $conditions.Devices.DeviceFilter.Mode = $DeviceFilterMode - } - if (-not $conditions.Devices.DeviceFilter.Contains('Rule')) - { $conditions.Devices.DeviceFilter.Add('Rule', $DeviceFilterRule) } else { - $conditions.Devices.DeviceFilter.Rule = $DeviceFilterRule + if (-not $conditions.Devices.DeviceFilter.Contains('Mode')) + { + $conditions.Devices.DeviceFilter.Add('Mode', $DeviceFilterMode) + } + else + { + $conditions.Devices.DeviceFilter.Mode = $DeviceFilterMode + } + if (-not $conditions.Devices.DeviceFilter.Contains('Rule')) + { + $conditions.Devices.DeviceFilter.Add('Rule', $DeviceFilterRule) + } + else + { + $conditions.Devices.DeviceFilter.Rule = $DeviceFilterRule + } } } } @@ -1476,23 +1452,27 @@ function Set-TargetResource Write-Verbose -Message 'Set-Targetresource: process risk levels and app types' Write-Verbose -Message "Set-Targetresource: UserRiskLevels: $UserRiskLevels" - If (!$currentParameters.ContainsKey('UserRiskLevels') -and $null -ne $currentPolicy.UserRiskLevels) { - $UserRiskLevels = $currentPolicy.UserRiskLevels + If ($currentParameters.ContainsKey('UserRiskLevels')) + { + $Conditions.Add('UserRiskLevels', $UserRiskLevels) + #no translation or conversion needed } - $Conditions.Add('UserRiskLevels', $UserRiskLevels) - #no translation or conversion needed + + Write-Verbose -Message "Set-Targetresource: SignInRiskLevels: $SignInRiskLevels" - If (!$currentParameters.ContainsKey('SignInRiskLevels') -and $null -ne $currentPolicy.SignInRiskLevels) { - $SignInRiskLevels = $currentPolicy.SignInRiskLevels + If ($currentParameters.ContainsKey('SignInRiskLevels')) + { + $Conditions.Add('SignInRiskLevels', $SignInRiskLevels) + #no translation or conversion needed } - $Conditions.Add('SignInRiskLevels', $SignInRiskLevels) - #no translation or conversion needed + + Write-Verbose -Message "Set-Targetresource: ClientAppTypes: $ClientAppTypes" - If (!$currentParameters.ContainsKey('ClientAppTypes') -and $null -ne $currentPolicy.ClientAppTypes) { - $ClientAppTypes = $currentPolicy.ClientAppTypes + If ($currentParameters.ContainsKey('ClientAppTypes')) + { + $Conditions.Add('ClientAppTypes', $ClientAppTypes) + #no translation or conversion needed } - $Conditions.Add('ClientAppTypes', $ClientAppTypes) - #no translation or conversion needed Write-Verbose -Message 'Set-Targetresource: Adding processed conditions' #add all conditions to the parameter list $NewParameters.Add('Conditions', $Conditions) @@ -1636,19 +1616,32 @@ function Set-TargetResource Write-Verbose -Message "Set-Targetresource: create policy $DisplayName" Write-Verbose -Message 'Create Parameters:' Write-Verbose -Message (Convert-M365DscHashtableToString $NewParameters) - try + + if ($newparameters.Conditions.applications.count -gt 0 -and $newparameters.Conditions.Users.count -gt 0 -and ($newparameters.GrantControls.count -gt 0 -or $newparameters.SessionControls.count -gt 0)) { - New-MgBetaIdentityConditionalAccessPolicy @NewParameters + try + { + New-MgBetaIdentityConditionalAccessPolicy @NewParameters + } + catch + { + New-M365DSCLogEntry -Message 'Error creating new policy:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + Write-Verbose -Message 'Set-Targetresource: Failed creating new policy' + } } - catch + else { - New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + New-M365DSCLogEntry -Message 'Error creating new policy:' ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential - Write-Verbose -Message 'Set-Targetresource: Failed creating policy' + Write-Verbose -Message 'Set-Targetresource: Failed creating new policy. At least a user rule, application rule and grant or session control is required' } } elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConditionalAccessPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConditionalAccessPolicy.Tests.ps1 index 22aa9e4086..8d87fc35f5 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConditionalAccessPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConditionalAccessPolicy.Tests.ps1 @@ -296,6 +296,124 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name 'Policy exists but is not in the Desired State. Not all params specified' -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'Allin' + Ensure = 'Present' + Credential = $Credscredential + State = 'disabled' + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationStrengthPolicy -MockWith { + return @{ + Id = "00000000-0000-0000-0000-000000000004" + DisplayName = "Phishing-resistant MFA" + } + } + + Mock -CommandName Get-MgBetaIdentityConditionalAccessPolicy -MockWith { + return @{ + Id = 'bcc0cf19-ee89-46f0-8e12-4b89123ee6f9' + DisplayName = 'Allin' + State = 'enabled' + Conditions = @{ + Applications = @{ + IncludeApplications = @('All') + ExcludeApplications = @('00000012-0000-0000-c000-000000000000', 'Office365') + IncludeUserActions = @('urn:user:registersecurityinfo') + } + Users = @{ + IncludeUsers = 'All' + ExcludeUsers = '76d3c3f6-8269-462b-9385-37435cb33f1e' + IncludeGroups = @('f1eb1a09-c0c2-4df4-9e69-fee01f00db31') + ExcludeGroups = @('f1eb1a09-c0c2-4df4-9e69-fee01f00db31') + IncludeRoles = @('17315797-102d-40b4-93e0-432062caca18') + ExcludeRoles = @('17315797-102d-40b4-93e0-432062caca18') + } + Platforms = @{ + IncludePlatforms = @('Android', 'IOS') + ExcludePlatforms = @('Windows', 'WindowsPhone', 'MacOS') + } + Locations = @{ + IncludeLocations = 'AllTrusted' + ExcludeLocations = '9e4ca5f3-0ba9-4257-b906-74d3038ac970' + } + Devices = @{ + IncludeDevices = @('All') + ExcludeDevices = @('Compliant', 'DomainJoined') + } + ClientAppTypes = @('Browser', 'MobileAppsAndDesktopClients') + SignInRiskLevels = @('High') + UserRiskLevels = @('High') + } + GrantControls = @{ + _Operator = 'AND' + BuiltInControls = @('Mfa', 'CompliantDevice', 'DomainJoinedDevice', 'ApprovedApplication', 'CompliantApplication') + AuthenticationStrength = @{ + Id = "00000000-0000-0000-0000-000000000004" + } + } + SessionControls = @{ + ApplicationEnforcedRestrictions = @{ + IsEnabled = $True + } + CloudAppSecurity = @{ + IsEnabled = $True + CloudAppSecurityType = 'MonitorOnly' + } + SignInFrequency = @{ + IsEnabled = $True + Type = 'Days' + Value = 5 + } + PersistentBrowser = @{ + IsEnabled = $True + Mode = 'Always' + } + } + } + } + Mock -CommandName Get-MgUser -MockWith { + return @{ + Id = '76d3c3f6-8269-462b-9385-37435cb33f1e' + UserPrincipalName = 'alexw@contoso.com' + } + } + Mock -CommandName Get-MgGroup -MockWith { + return @{ + Id = 'f1eb1a09-c0c2-4df4-9e69-fee01f00db31' + DisplayName = 'Group 01' + } + } + Mock -CommandName Get-MgBetaDirectoryRoleTemplate -MockWith { + return @{ + Id = '17315797-102d-40b4-93e0-432062caca18' + DisplayName = 'Compliance Administrator' + } + } + Mock -CommandName Get-MgBetaIdentityConditionalAccessNamedLocation -MockWith { + return @{ + Id = '9e4ca5f3-0ba9-4257-b906-74d3038ac970' + DisplayName = 'Contoso LAN' + } + } + } + + It 'Should return Present from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should update the settings from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaIdentityConditionalAccessPolicy -Exactly 1 + } + } + Context -Name 'Policy exists and is already in the Desired State' -Fixture { BeforeAll { $testParams = @{