Skip to content

Commit 90fef47

Browse files
authored
Merge pull request #558 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 1703d1d + 5404a56 commit 90fef47

File tree

4 files changed

+116
-13
lines changed

4 files changed

+116
-13
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Function Invoke-ExecOffboardTenant {
1+
function Invoke-ExecOffboardTenant {
22
<#
33
.FUNCTIONALITY
44
Entrypoint
@@ -84,7 +84,7 @@ Function Invoke-ExecOffboardTenant {
8484
$property = $_
8585
$propertyContacts = $orgContacts.($($property))
8686

87-
if ($propertyContacts -AND ($domains -notcontains ($propertyContacts | ForEach-Object { $_.Split('@')[1] }))) {
87+
if ($propertyContacts -and ($domains -notcontains ($propertyContacts | ForEach-Object { $_.Split('@')[1] }))) {
8888
$newPropertyContent = [System.Collections.Generic.List[object]]($propertyContacts | Where-Object { $domains -notcontains $_.Split('@')[1] })
8989

9090
$patchContactBody = if (!($newPropertyContent)) { "{ `"$($property)`" : [] }" } else { [pscustomobject]@{ $property = $newPropertyContent } | ConvertTo-Json }
@@ -103,6 +103,29 @@ Function Invoke-ExecOffboardTenant {
103103
# TODO Add logic for privacyProfile later - rvdwegen
104104

105105
}
106+
107+
if ($request.body.RemoveDomainAnalyserData -eq $true) {
108+
# Remove all Domain Analyser data for this tenant
109+
try {
110+
$DomainTable = Get-CIPPTable -Table 'Domains'
111+
$Filter = "TenantGUID eq '{0}'" -f $TenantId
112+
$DomainEntries = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter
113+
114+
if ($DomainEntries) {
115+
$DomainCount = ($DomainEntries | Measure-Object).Count
116+
foreach ($Domain in $DomainEntries) {
117+
Remove-AzDataTableEntity @DomainTable -Entity $Domain
118+
}
119+
$Results.Add("Successfully removed $DomainCount Domain Analyser entries")
120+
Write-LogMessage -headers $Request.Headers -API $APIName -message "Removed $DomainCount Domain Analyser entries" -Sev 'Info' -tenant $TenantFilter
121+
} else {
122+
$Results.Add('No Domain Analyser data found for this tenant')
123+
}
124+
} catch {
125+
$Errors.Add("Failed to remove Domain Analyser data: $($_.Exception.message)")
126+
}
127+
}
128+
106129
$VendorApps = $Request.Body.vendorApplications
107130
if ($VendorApps) {
108131
$VendorApps | ForEach-Object {

Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,19 @@ function Invoke-CIPPStandardConditionalAccessTemplate {
6666
continue
6767
}
6868
}
69-
$null = New-CIPPCAPolicy -replacePattern 'displayName' -TenantFilter $tenant -state $Setting.state -RawJSON $JSONObj -Overwrite $true -APIName $APIName -Headers $Request.Headers -DisableSD $Setting.DisableSD
69+
$NewCAPolicy = @{
70+
replacePattern = 'displayName'
71+
TenantFilter = $Tenant
72+
state = $Setting.state
73+
RawJSON = $JSONObj
74+
Overwrite = $true
75+
APIName = 'Standards'
76+
Headers = $Request.Headers
77+
DisableSD = $Setting.DisableSD
78+
CreateGroups = $Setting.CreateGroups ?? $false
79+
}
80+
81+
$null = New-CIPPCAPolicy @NewCAPolicy
7082
} catch {
7183
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
7284
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName). Error: $ErrorMessage" -sev 'Error'

Modules/CIPPCore/Public/TenantGroups/Update-CIPPDynamicTenantGroups.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ function Update-CIPPDynamicTenantGroups {
161161
}
162162
Add-CIPPAzDataTableEntity @LicenseCacheTable -Entity $CacheEntity -Force
163163
} catch {
164-
Write-LogMessage -API 'TenantGroups' -message 'Error getting licenses' -Tenant $_.defaultDomainName -sev Warning -LogData (Get-CippExeception -Exception $_)
164+
Write-LogMessage -API 'TenantGroups' -message 'Error getting licenses' -Tenant $_.defaultDomainName -sev Warning -LogData (Get-CippException -Exception $_)
165165
}
166166
}
167167
}

0 commit comments

Comments
 (0)