@@ -8,6 +8,7 @@ function New-CIPPCAPolicy {
88 $Overwrite ,
99 $ReplacePattern = ' none' ,
1010 $DisableSD = $false ,
11+ $CreateGroups = $false ,
1112 $APIName = ' Create CA Policy' ,
1213 $Headers
1314 )
@@ -39,7 +40,7 @@ function New-CIPPCAPolicy {
3940 }
4041 # Helper function to replace group display names with GUIDs
4142 function Replace-GroupNameWithId {
42- param ($groupNames )
43+ param ($TenantFilter , $ groupNames, $CreateGroups , $GroupTemplates )
4344
4445 $GroupIds = [System.Collections.Generic.List [string ]]::new()
4546 $groupNames | ForEach-Object {
@@ -54,6 +55,28 @@ function New-CIPPCAPolicy {
5455 $null = Write-LogMessage - Headers $User - API ' Create CA Policy' - message " Replaced group name $_ with ID $gid " - Sev ' Debug'
5556 $GroupIds.Add ($gid ) # add the ID to the list
5657 }
58+ } elseif ($CreateGroups ) {
59+ Write-Warning " Creating group $_ as it does not exist in the tenant"
60+ if ($GroupTemplates.displayName -eq $_ ) {
61+ Write-Information " Creating group from template for $_ "
62+ $GroupTemplate = $GroupTemplates | Where-Object - Property displayName -EQ $_
63+ $NewGroup = New-CIPPGroup - GroupObject $GroupTemplate - TenantFilter $TenantFilter - APIName ' New-CIPPCAPolicy'
64+ $GroupIds.Add ($NewGroup.GroupId )
65+ } else {
66+ Write-Information " No template found, creating security group for $_ "
67+ $username = $_ -replace ' [^a-zA-Z0-9]' , ' '
68+ if ($username.Length -gt 64 ) {
69+ $username = $username.Substring (0 , 64 )
70+ }
71+ $GroupObject = @ {
72+ groupType = ' generic'
73+ displayName = $_
74+ username = $username
75+ securityEnabled = $true
76+ }
77+ $NewGroup = New-CIPPGroup - GroupObject $GroupObject - TenantFilter $TenantFilter - APIName ' New-CIPPCAPolicy'
78+ $GroupIds.Add ($NewGroup.GroupId )
79+ }
5780 } else {
5881 Write-Warning " Group $_ not found in the tenant"
5982 }
@@ -185,10 +208,31 @@ function New-CIPPCAPolicy {
185208 if ($JSONobj.conditions.users.excludeGroups ) { $JSONobj.conditions.users.excludeGroups = @ () }
186209 }
187210 ' displayName' {
211+ $TemplatesTable = Get-CIPPTable - tablename ' templates'
212+ $GroupTemplates = Get-CIPPAzDataTableEntity @TemplatesTable - filter " PartitionKey eq 'GroupTemplate'" | ForEach-Object {
213+ if ($_.JSON -and (Test-Json - Json $_.JSON - ErrorAction SilentlyContinue)) {
214+ $Group = $_.JSON | ConvertFrom-Json
215+ $Group
216+ }
217+ }
188218 try {
189219 Write-Information ' Replacement pattern for inclusions and exclusions is displayName.'
190- $users = New-GraphGETRequest - uri ' https://graph.microsoft.com/beta/users?$select=id,displayName' - tenantid $TenantFilter - asApp $true
191- $groups = New-GraphGETRequest - uri ' https://graph.microsoft.com/beta/groups?$select=id,displayName' - tenantid $TenantFilter - asApp $true
220+ $Requests = @ (
221+ @ {
222+ url = ' users?$select=id,displayName&$top=999'
223+ method = ' GET'
224+ id = ' users'
225+ }
226+ @ {
227+ url = ' groups?$select=id,displayName&$top=999'
228+ method = ' GET'
229+ id = ' groups'
230+ }
231+ )
232+ $BulkResults = New-GraphBulkRequest - Requests $Requests - tenantid $TenantFilter - asapp $true
233+
234+ $users = ($BulkResults | Where-Object { $_.id -eq ' users' }).body.value
235+ $groups = ($BulkResults | Where-Object { $_.id -eq ' groups' }).body.value
192236
193237 foreach ($userType in ' includeUsers' , ' excludeUsers' ) {
194238 if ($JSONobj.conditions.users.PSObject.Properties.Name -contains $userType -and $JSONobj.conditions.users .$userType -notin ' All' , ' None' , ' GuestOrExternalUsers' ) {
@@ -199,7 +243,7 @@ function New-CIPPCAPolicy {
199243 # Check the included and excluded groups
200244 foreach ($groupType in ' includeGroups' , ' excludeGroups' ) {
201245 if ($JSONobj.conditions.users.PSObject.Properties.Name -contains $groupType ) {
202- $JSONobj.conditions.users .$groupType = @ (Replace- GroupNameWithId - groupNames $JSONobj.conditions.users .$groupType )
246+ $JSONobj.conditions.users .$groupType = @ (Replace- GroupNameWithId - groupNames $JSONobj.conditions.users .$groupType - CreateGroups $CreateGroups - TenantFilter $TenantFilter - GroupTemplates $GroupTemplates )
203247 }
204248 }
205249 } catch {
@@ -246,18 +290,42 @@ function New-CIPPCAPolicy {
246290 Write-Information $RawJSON
247291 try {
248292 Write-Information ' Checking for existing policies'
249- $CheckExististing = New-GraphGETRequest - uri ' https://graph.microsoft.com/beta/identity/conditionalAccess/policies' - tenantid $TenantFilter - asApp $true | Where-Object - Property displayName -EQ $displayname
250- if ($CheckExististing ) {
293+ $CheckExisting = New-GraphGETRequest - uri ' https://graph.microsoft.com/beta/identity/conditionalAccess/policies' - tenantid $TenantFilter - asApp $true | Where-Object - Property displayName -EQ $displayname
294+ if ($CheckExisting ) {
251295 if ($Overwrite -ne $true ) {
252296 throw " Conditional Access Policy with Display Name $ ( $Displayname ) Already exists"
253297 return $false
254298 } else {
255299 if ($State -eq ' donotchange' ) {
256- $JSONobj.state = $CheckExististing .state
300+ $JSONobj.state = $CheckExisting .state
257301 $RawJSON = ConvertTo-Json - InputObject $JSONobj - Depth 10 - Compress
258302 }
259- Write-Information " overwriting $ ( $CheckExististing.id ) "
260- $null = New-GraphPOSTRequest - uri " https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$ ( $CheckExististing.id ) " - tenantid $tenantfilter - type PATCH - body $RawJSON - asApp $true
303+ # Preserve any exclusion groups named "Vacation Exclusion - <PolicyDisplayName>" from existing policy
304+ try {
305+ $ExistingVacationGroup = New-GraphGETRequest - uri " https://graph.microsoft.com/beta/groups?`$ filter=startsWith(displayName,'Vacation Exclusion')&`$ select=id,displayName&`$ top=999&`$ count=true" - ComplexFilter - tenantid $TenantFilter - asApp $true |
306+ Where-Object { $CheckExisting.conditions.users.excludeGroups -contains $_.id }
307+ if ($ExistingVacationGroup ) {
308+ if (-not ($JSONobj.conditions.users.PSObject.Properties.Name -contains ' excludeGroups' )) {
309+ $JSONobj.conditions.users | Add-Member - NotePropertyName ' excludeGroups' - NotePropertyValue @ () - Force
310+ }
311+ if ($JSONobj.conditions.users.excludeGroups -notcontains $ExistingVacationGroup.id ) {
312+ Write-Information " Preserving vacation exclusion group $ ( $ExistingVacationGroup.displayName ) "
313+ $NewExclusions = [system.collections.generic.list [string ]]::new()
314+ # Convert each item to string explicitly to avoid type conversion issues
315+ foreach ($group in $JSONobj.conditions.users.excludeGroups ) {
316+ $NewExclusions.Add ([string ]$group )
317+ }
318+ $NewExclusions.Add ($ExistingVacationGroup.id )
319+ $JSONobj.conditions.users.excludeGroups = $NewExclusions
320+ }
321+ # Re-render RawJSON after modification
322+ $RawJSON = ConvertTo-Json - InputObject $JSONobj - Depth 10 - Compress
323+ }
324+ } catch {
325+ Write-Information " Failed to preserve vacation exclusion group: $ ( $_.Exception.Message ) "
326+ }
327+ Write-Information " overwriting $ ( $CheckExisting.id ) "
328+ $null = New-GraphPOSTRequest - uri " https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$ ( $CheckExisting.id ) " - tenantid $tenantfilter - type PATCH - body $RawJSON - asApp $true
261329 Write-LogMessage - Headers $User - API ' Create CA Policy' - tenant $ ($Tenant ) - message " Updated Conditional Access Policy $ ( $JSONobj.Displayname ) to the template standard." - Sev ' Info'
262330 return " Updated policy $displayname for $tenantfilter "
263331 }
0 commit comments