Skip to content

Commit 1703d1d

Browse files
authored
Merge pull request #557 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 989f4f3 + 2d23f5c commit 1703d1d

File tree

6 files changed

+142
-13
lines changed

6 files changed

+142
-13
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ function Invoke-ExecCAExclusion {
1818
$EndDate = $Request.Body.EndDate
1919
$PolicyId = $Request.Body.PolicyId
2020
$ExclusionType = $Request.Body.ExclusionType
21+
$ExcludeLocationAuditAlerts = $Request.Body.excludeLocationAuditAlerts
2122

2223
if ($Users) {
2324
$UserID = $Users.value
@@ -61,6 +62,12 @@ function Invoke-ExecCAExclusion {
6162
if ($Request.Body.vacation -eq 'true') {
6263
$StartDate = $Request.Body.StartDate
6364
$EndDate = $Request.Body.EndDate
65+
# Detect if policy targets specific named locations (GUIDs) and user requested audit log exclusion
66+
$GuidRegex = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
67+
$LocationIds = @()
68+
if ($Policy.conditions.locations.includeLocations) { $LocationIds += $Policy.conditions.locations.includeLocations }
69+
if ($Policy.conditions.locations.excludeLocations) { $LocationIds += $Policy.conditions.locations.excludeLocations }
70+
$PolicyHasGuidLocations = $LocationIds | Where-Object { $_ -match $GuidRegex }
6471

6572
$Parameters = [PSCustomObject]@{
6673
GroupType = 'Security'
@@ -82,6 +89,18 @@ function Invoke-ExecCAExclusion {
8289
Write-Information ($TaskBody | ConvertTo-Json -Depth 10)
8390

8491
Add-CIPPScheduledTask -Task $TaskBody -hidden $false
92+
# Optional: schedule audit log exclusion add task if requested and policy has location GUIDs
93+
if ($ExcludeLocationAuditAlerts -and $PolicyHasGuidLocations) {
94+
$AuditUsers = $Users.addedFields.userPrincipalName ?? $Users.value ?? $Users ?? $UserID
95+
$AuditAddTask = [pscustomobject]@{
96+
TenantFilter = $TenantFilter
97+
Name = "Add Audit Log Location Exclusion: $PolicyName"
98+
Command = @{ value = 'Set-CIPPAuditLogUserExclusion'; label = 'Set-CIPPAuditLogUserExclusion' }
99+
Parameters = [pscustomobject]@{ Users = $AuditUsers; Action = 'Add'; Type = 'Location' }
100+
ScheduledTime = $StartDate
101+
}
102+
Add-CIPPScheduledTask -Task $AuditAddTask -hidden $true
103+
}
85104
#Removal of the exclusion
86105
$TaskBody.Command = @{
87106
label = 'Remove-CIPPGroupMember'
@@ -90,6 +109,17 @@ function Invoke-ExecCAExclusion {
90109
$TaskBody.Name = "Remove CA Exclusion Vacation Mode: $PolicyName"
91110
$TaskBody.ScheduledTime = $EndDate
92111
Add-CIPPScheduledTask -Task $TaskBody -hidden $false
112+
if ($ExcludeLocationAuditAlerts -and $PolicyHasGuidLocations) {
113+
$AuditUsers = $Users.addedFields.userPrincipalName ?? $Users.value ?? $Users ?? $UserID
114+
$AuditRemoveTask = [pscustomobject]@{
115+
TenantFilter = $TenantFilter
116+
Name = "Remove Audit Log Location Exclusion: $PolicyName"
117+
Command = @{ value = 'Set-CIPPAuditLogUserExclusion'; label = 'Set-CIPPAuditLogUserExclusion' }
118+
Parameters = [pscustomobject]@{ Users = $AuditUsers; Action = 'Remove'; Type = 'Location' }
119+
ScheduledTime = $EndDate
120+
}
121+
Add-CIPPScheduledTask -Task $AuditRemoveTask -hidden $true
122+
}
93123
$body = @{ Results = "Successfully added vacation mode schedule for $Username." }
94124
} else {
95125
$Parameters = @{

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecUpdateDriftDeviation.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ function Invoke-ExecUpdateDriftDeviation {
4444
$StandardTemplate = Get-CIPPTenantAlignment -TenantFilter $TenantFilter | Where-Object -Property standardType -EQ 'drift'
4545
if ($Setting -like '*IntuneTemplate*') {
4646
$Setting = 'IntuneTemplate'
47-
$TemplateId = $Deviation.standardName.split('.') | Select-Object -Last 1
48-
$StandardTemplate = $StandardTemplate.standardSettings.IntuneTemplate | Where-Object { $_.TemplateList.value -eq $TemplateId }
47+
$TemplateId = $Deviation.standardName.split('.') | Select-Object -Index 2
48+
$StandardTemplate = $StandardTemplate.standardSettings.IntuneTemplate | Where-Object { $_.TemplateList.value -like "*$TemplateId*" }
4949
$StandardTemplate | Add-Member -MemberType NoteProperty -Name 'remediate' -Value $true -Force
5050
$StandardTemplate | Add-Member -MemberType NoteProperty -Name 'report' -Value $true -Force
5151
$Settings = $StandardTemplate
5252
} elseif ($Setting -like '*ConditionalAccessTemplate*') {
5353
$Setting = 'ConditionalAccessTemplate'
54-
$TemplateId = $Deviation.standardName.split('.') | Select-Object -Last 1
55-
$StandardTemplate = $StandardTemplate.standardSettings.ConditionalAccessTemplate | Where-Object { $_.TemplateList.value -eq $TemplateId }
54+
$TemplateId = $Deviation.standardName.split('.') | Select-Object -Index 2
55+
$StandardTemplate = $StandardTemplate.standardSettings.ConditionalAccessTemplate | Where-Object { $_.TemplateList.value -like "*$TemplateId*" }
5656
$StandardTemplate | Add-Member -MemberType NoteProperty -Name 'remediate' -Value $true -Force
5757
$StandardTemplate | Add-Member -MemberType NoteProperty -Name 'report' -Value $true -Force
5858
$Settings = $StandardTemplate

Modules/CIPPCore/Public/Get-CIPPDrift.ps1

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ function Get-CIPPDrift {
4747
}
4848
} | Sort-Object -Property displayName
4949

50+
# Load all CA templates
51+
$CAFilter = "PartitionKey eq 'CATemplate'"
52+
$RawCATemplates = (Get-CIPPAzDataTableEntity @IntuneTable -Filter $CAFilter)
53+
$AllCATemplates = $RawCATemplates | ForEach-Object {
54+
try {
55+
$data = $_.JSON | ConvertFrom-Json -Depth 100 -ErrorAction SilentlyContinue
56+
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.RowKey -Force
57+
$data
58+
} catch {
59+
# Skip invalid templates
60+
}
61+
} | Sort-Object -Property displayName
62+
5063
try {
5164
$AlignmentData = Get-CIPPTenantAlignment -TenantFilter $TenantFilter -TemplateId $TemplateId | Where-Object -Property standardType -EQ 'drift'
5265
if (-not $AlignmentData) {
@@ -82,18 +95,35 @@ function Get-CIPPDrift {
8295
} else {
8396
'New'
8497
}
98+
# Reset displayName and description for each deviation to prevent carryover from previous iterations
99+
$displayName = $null
100+
$standardDescription = $null
85101
#if the $ComparisonItem.StandardName contains *intuneTemplate*, then it's an Intune policy deviation, and we need to grab the correct displayname from the template table
86102
if ($ComparisonItem.StandardName -like '*intuneTemplate*') {
87103
$CompareGuid = $ComparisonItem.StandardName.Split('.') | Select-Object -Index 2
88104
Write-Host "Extracted GUID: $CompareGuid"
89105
$Template = $AllIntuneTemplates | Where-Object { $_.GUID -like "*$CompareGuid*" }
90-
if ($Template) { $displayName = $Template.displayName }
106+
if ($Template) {
107+
$displayName = $Template.displayName
108+
$standardDescription = $Template.description
109+
}
110+
}
111+
# Handle Conditional Access templates
112+
if ($ComparisonItem.StandardName -like '*ConditionalAccessTemplate*') {
113+
$CompareGuid = $ComparisonItem.StandardName.Split('.') | Select-Object -Index 2
114+
Write-Host "Extracted CA GUID: $CompareGuid"
115+
$Template = $AllCATemplates | Where-Object { $_.GUID -like "*$CompareGuid*" }
116+
if ($Template) {
117+
$displayName = $Template.displayName
118+
$standardDescription = $Template.description
119+
}
91120
}
92121
$reason = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) { $ExistingDriftStates[$ComparisonItem.StandardName].Reason }
93122
$User = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) { $ExistingDriftStates[$ComparisonItem.StandardName].User }
94123
$StandardsDeviations.Add([PSCustomObject]@{
95124
standardName = $ComparisonItem.StandardName
96125
standardDisplayName = $displayName
126+
standardDescription = $standardDescription
97127
expectedValue = 'Compliant'
98128
receivedValue = $ComparisonItem.StandardValue
99129
state = 'current'
@@ -203,14 +233,6 @@ function Get-CIPPDrift {
203233
# Get actual CA templates from templates table
204234
if ($CATemplateIds.Count -gt 0) {
205235
try {
206-
$CATable = Get-CippTable -tablename 'templates'
207-
$CAFilter = "PartitionKey eq 'CATemplate'"
208-
$AllCATemplates = (Get-CIPPAzDataTableEntity @CATable -Filter $CAFilter) | ForEach-Object {
209-
$data = $_.JSON | ConvertFrom-Json -Depth 100
210-
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force
211-
$data
212-
} | Sort-Object -Property displayName
213-
214236
$TemplateCATemplates = $AllCATemplates | Where-Object { $_.GUID -in $CATemplateIds }
215237
} catch {
216238
Write-Warning "Failed to get CA templates: $($_.Exception.Message)"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
function Set-CIPPAuditLogUserExclusion {
2+
<#
3+
.SYNOPSIS
4+
Sets user exclusions for Audit Log alerting.
5+
.DESCRIPTION
6+
This function allows you to add or remove user exclusions for Audit Log alerting in a specified tenant
7+
by updating the AuditLogUserExclusions CIPP table.
8+
.PARAMETER TenantFilter
9+
The tenant identifier for which to set the user exclusions.
10+
.PARAMETER Users
11+
An array of user identifiers (GUIDs or UPNs) to be added or removed from the exclusion list.
12+
.PARAMETER Action
13+
The action to perform: 'Add' to add users to the exclusion list, 'Remove' to remove users from the exclusion list.
14+
.PARAMETER Headers
15+
The headers to include in the request, typically containing authentication tokens. This is supplied automatically by the API.
16+
#>
17+
[CmdletBinding(SupportsShouldProcess = $true)]
18+
param(
19+
[Parameter(Mandatory = $true)]
20+
[string]$TenantFilter,
21+
[Parameter(Mandatory = $true)]
22+
[string[]]$Users,
23+
[ValidateSet('Add', 'Remove')]
24+
[string]$Action = 'Add',
25+
[ValidateSet('Location')]
26+
[string]$Type = 'Location',
27+
$Headers
28+
)
29+
30+
$AuditLogExclusionsTable = Get-CIPPTable -tablename 'AuditLogUserExclusions'
31+
$ExistingEntries = Get-CIPPAzDataTableEntity @AuditLogExclusionsTable -Filter "PartitionKey eq '$TenantFilter'"
32+
33+
$Results = foreach ($User in $Users) {
34+
if ($Action -eq 'Add') {
35+
$ExistingUser = $ExistingEntries | Where-Object { $_.RowKey -eq $User -and $_.PartitionKey -eq $TenantFilter -and $_.Type -eq $Type }
36+
if (!$ExistingUser) {
37+
$NewEntry = [PSCustomObject]@{
38+
PartitionKey = $TenantFilter
39+
RowKey = $User
40+
ExcludedOn = (Get-Date).ToString('o')
41+
Type = $Type
42+
}
43+
if ($PSCmdlet.ShouldProcess("Adding exclusion for user: $User")) {
44+
Add-CIPPAzDataTableEntity @AuditLogExclusionsTable -Entity $NewEntry
45+
"Added audit log exclusion for user: $User"
46+
Write-LogMessage -headers $Headers -API 'Set-CIPPAuditLogUserExclusion' -message "Added audit log exclusion for user: $User" -Sev 'Info' -tenant $TenantFilter -LogData $NewEntry
47+
}
48+
} else {
49+
"User $User is already excluded."
50+
}
51+
} elseif ($Action -eq 'Remove') {
52+
if ($ExistingEntries.RowKey -contains $User) {
53+
if ($PSCmdlet.ShouldProcess("Removing exclusion for user: $User")) {
54+
$Entity = $ExistingEntries | Where-Object { $_.RowKey -eq $User -and $_.PartitionKey -eq $TenantFilter -and $_.Type -eq $Type }
55+
Remove-AzDataTableEntity @AuditLogExclusionsTable -Entity $Entity
56+
Write-LogMessage -headers $Headers -API 'Set-CIPPAuditLogUserExclusion' -message "Removed audit log exclusion for user: $User" -Sev 'Info' -tenant $TenantFilter -LogData $Entity
57+
"Removed audit log exclusion for user: $User"
58+
}
59+
} else {
60+
"User $User is not in the exclusion list."
61+
}
62+
}
63+
}
64+
return @($Results)
65+
}
66+

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ function Invoke-CIPPStandardConditionalAccessTemplate {
7676
if ($Settings.report -eq $true -or $Settings.remediate -eq $true) {
7777
$Filter = "PartitionKey eq 'CATemplate'"
7878
$Policies = (Get-CippAzDataTableEntity @Table -Filter $Filter | Where-Object RowKey -In $Settings.TemplateList.value).JSON | ConvertFrom-Json -Depth 10
79+
$AllCAPolicies = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies?$top=999' -tenantid $Tenant -asApp $true
7980
#check if all groups.displayName are in the existingGroups, if not $fieldvalue should contain all missing groups, else it should be true.
8081
$MissingPolicies = foreach ($Setting in $Settings.TemplateList) {
8182
$policy = $Policies | Where-Object { $_.displayName -eq $Setting.label }

Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ function Test-CIPPAuditLogRules {
185185
throw $_
186186
}
187187

188+
$AuditLogUserExclusions = Get-CIPPTable -TableName 'AuditLogUserExclusions'
189+
$ExcludedUsers = Get-CIPPAzDataTableEntity @AuditLogUserExclusions -Filter "PartitionKey eq '$TenantFilter'"
190+
188191
if ($LogCount -gt 0) {
189192
$LocationTable = Get-CIPPTable -TableName 'knownlocationdbv2'
190193
$ProcessedData = foreach ($AuditRecord in $SearchResults) {
@@ -341,6 +344,13 @@ function Test-CIPPAuditLogRules {
341344
if ($condition.Property.label -eq 'CIPPGeoLocation' -and !$AddedLocationCondition) {
342345
$conditionStrings.Add("`$_.HasLocationData -eq `$true")
343346
$CIPPClause.Add('HasLocationData is true')
347+
$ExcludedUsers = $ExcludedUsers | Where-Object { $_.Type -eq 'Location' }
348+
# Build single -notin condition against all excluded user keys
349+
$ExcludedUserKeys = @($ExcludedUsers.RowKey)
350+
if ($ExcludedUserKeys.Count -gt 0) {
351+
$conditionStrings.Add("`$(`$_.CIPPUserKey) -notin @('$($ExcludedUserKeys -join "', '")')")
352+
$CIPPClause.Add("CIPPUserKey not in [$($ExcludedUserKeys -join ', ')]")
353+
}
344354
$AddedLocationCondition = $true
345355
}
346356
$value = if ($condition.Input.value -is [array]) {

0 commit comments

Comments
 (0)