Skip to content

Commit 3f3d9fb

Browse files
fix(standards): support plain-string displayName in QuarantineTemplate
Drift remediation and hand-built templates can pass displayName as a plain string rather than an autoComplete object with a .value property. This caused QuarantineTemplate comparisons to fail silently. Also adds drift deviation resolution for QuarantineTemplate (hex-encoded policy name) and ReusableSettingsTemplate, and improves the error message when a setting cannot be resolved from drift template settings. Synced from CyberDrain/CIPP@8cee804
1 parent e04dbd6 commit 3f3d9fb

2 files changed

Lines changed: 50 additions & 8 deletions

File tree

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,40 @@ function Invoke-ExecUpdateDriftDeviation {
123123
$MatchedTemplate | Add-Member -MemberType NoteProperty -Name 'report' -Value $true -Force
124124
$Settings = $MatchedTemplate
125125
}
126+
} elseif ($Setting -like '*QuarantineTemplate*') {
127+
$Setting = 'QuarantineTemplate'
128+
# The suffix is the quarantine policy display name, hex encoded because '\', '#'
129+
# and '?' are legal in a quarantine name but not in an Azure Table RowKey.
130+
# See the matching encoder in Invoke-CIPPStandardQuarantineTemplate.
131+
$HexName = $Deviation.standardName -replace '^(standards\.)?QuarantineTemplates?\.', ''
132+
$PolicyName = $null
133+
if ($HexName -match '^[0-9A-Fa-f]+$' -and $HexName.Length % 2 -eq 0) {
134+
$Chars = for ($i = 0; $i -lt $HexName.Length; $i += 2) {
135+
[char][Convert]::ToInt32($HexName.Substring($i, 2), 16)
136+
}
137+
$PolicyName = -join $Chars
138+
}
139+
$MatchedTemplate = $StandardTemplate.standardSettings.QuarantineTemplate | Where-Object {
140+
($_.displayName.value ?? [string]$_.displayName) -eq $PolicyName
141+
} | Select-Object -First 1
142+
if (-not $MatchedTemplate) {
143+
Write-LogMessage -tenant $TenantFilter -Headers $Request.Headers -API $APINAME -message "Could not find QuarantineTemplate '$PolicyName' in drift standard settings for remediation" -Sev 'Warning'
144+
} else {
145+
$MatchedTemplate | Add-Member -MemberType NoteProperty -Name 'remediate' -Value $true -Force
146+
$MatchedTemplate | Add-Member -MemberType NoteProperty -Name 'report' -Value $true -Force
147+
$Settings = $MatchedTemplate
148+
}
149+
} elseif ($Setting -like '*ReusableSettingsTemplate*') {
150+
$Setting = 'ReusableSettingsTemplate'
151+
$TemplateId = $Deviation.standardName -replace '^(standards\.)?ReusableSettingsTemplates?\.', ''
152+
$MatchedTemplate = $StandardTemplate.standardSettings.ReusableSettingsTemplate | Where-Object { $_.TemplateList.value -like "*$TemplateId*" } | Select-Object -First 1
153+
if (-not $MatchedTemplate) {
154+
Write-LogMessage -tenant $TenantFilter -Headers $Request.Headers -API $APINAME -message "Could not find ReusableSettingsTemplate $TemplateId in drift standard settings for remediation" -Sev 'Warning'
155+
} else {
156+
$MatchedTemplate | Add-Member -MemberType NoteProperty -Name 'remediate' -Value $true -Force
157+
$MatchedTemplate | Add-Member -MemberType NoteProperty -Name 'report' -Value $true -Force
158+
$Settings = $MatchedTemplate
159+
}
126160
} else {
127161
$StandardTemplate = $StandardTemplate.standardSettings.$Setting
128162
# If the addedComponent values are stored nested under standards.<setting> instead of
@@ -191,7 +225,7 @@ function Invoke-ExecUpdateDriftDeviation {
191225
[PSCustomObject]@{
192226
standardName = $Deviation.standardName
193227
success = $false
194-
error = "The deviation status was updated, but no remediation task was scheduled: the template could not be resolved from the drift template settings. Verify the template still exists in the template library, or re-save the drift template."
228+
error = "The deviation status was updated, but no remediation task was scheduled: '$Setting' could not be resolved from the drift template settings. Verify the template still exists in the template library and is included in the drift template, or re-save the drift template."
195229
}
196230
}
197231
}

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardQuarantineTemplate.ps1

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ function Invoke-CIPPStandardQuarantineTemplate {
6363
# Compare the settings from standard with the current policies
6464
$CompareList = foreach ($Policy in $Settings) {
6565
try {
66+
# displayName comes from an autoComplete, so it is normally an object with a .value.
67+
# Drift remediation and hand-built templates can pass it as a plain string.
68+
$PolicyDisplayName = $Policy.displayName.value ?? [string]$Policy.displayName
69+
if ([string]::IsNullOrWhiteSpace($PolicyDisplayName)) {
70+
Write-LogMessage -API $APIName -tenant $Tenant -message 'Skipping a Quarantine policy entry with no display name.' -sev 'Warning'
71+
continue
72+
}
73+
6674
# Create hashtable with desired Quarantine Setting
6775
$EndUserQuarantinePermissions = @{
6876
# ViewHeader and Download are set to false because the value 0 or 1 does nothing per Microsoft documentation
@@ -77,13 +85,13 @@ function Invoke-CIPPStandardQuarantineTemplate {
7785
}
7886

7987
# If the Quarantine Policy already exists
80-
if ($Policy.displayName.value -in $CurrentPolicies.Name) {
88+
if ($PolicyDisplayName -in $CurrentPolicies.Name) {
8189
#Get the current policy and convert EndUserQuarantinePermissions from string to hashtable for compare
82-
$ExistingPolicy = $CurrentPolicies | Where-Object -Property Name -EQ $Policy.displayName.value
90+
$ExistingPolicy = $CurrentPolicies | Where-Object -Property Name -EQ $PolicyDisplayName
8391
$ExistingPolicyEndUserQuarantinePermissions = Convert-QuarantinePermissionsValue -InputObject $ExistingPolicy.EndUserQuarantinePermissions -ErrorAction Stop
8492

8593
#Compare the current policy
86-
$StateIsCorrect = ($ExistingPolicy.Name -eq $Policy.displayName.value) -and
94+
$StateIsCorrect = ($ExistingPolicy.Name -eq $PolicyDisplayName) -and
8795
($ExistingPolicy.ESNEnabled -eq $Policy.ESNEnabled) -and
8896
($ExistingPolicy.IncludeMessagesFromBlockedSenderAddress -eq $Policy.IncludeMessagesFromBlockedSenderAddress) -and
8997
(!(Compare-Object @($ExistingPolicyEndUserQuarantinePermissions.values) @($EndUserQuarantinePermissions.values)))
@@ -94,7 +102,7 @@ function Invoke-CIPPStandardQuarantineTemplate {
94102
missing = $false
95103
StateIsCorrect = $StateIsCorrect
96104
Action = 'None'
97-
displayName = $Policy.displayName.value
105+
displayName = $PolicyDisplayName
98106
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
99107
ESNEnabled = $Policy.ESNEnabled
100108
IncludeMessagesFromBlockedSenderAddress = $Policy.IncludeMessagesFromBlockedSenderAddress
@@ -109,7 +117,7 @@ function Invoke-CIPPStandardQuarantineTemplate {
109117
missing = $false
110118
StateIsCorrect = $StateIsCorrect
111119
Action = 'Update'
112-
displayName = $Policy.displayName.value
120+
displayName = $PolicyDisplayName
113121
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
114122
ESNEnabled = $Policy.ESNEnabled
115123
IncludeMessagesFromBlockedSenderAddress = $Policy.IncludeMessagesFromBlockedSenderAddress
@@ -125,7 +133,7 @@ function Invoke-CIPPStandardQuarantineTemplate {
125133
missing = $true
126134
StateIsCorrect = $false
127135
Action = 'Create'
128-
displayName = $Policy.displayName.value
136+
displayName = $PolicyDisplayName
129137
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
130138
ESNEnabled = $Policy.ESNEnabled
131139
IncludeMessagesFromBlockedSenderAddress = $Policy.IncludeMessagesFromBlockedSenderAddress
@@ -136,7 +144,7 @@ function Invoke-CIPPStandardQuarantineTemplate {
136144
}
137145
} catch {
138146
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
139-
$Message = "Failed to compare Quarantine policy $($Policy.displayName.value), Error: $ErrorMessage"
147+
$Message = "Failed to compare Quarantine policy $PolicyDisplayName, Error: $ErrorMessage"
140148
Write-LogMessage -API $APIName -tenant $tenant -message $Message -sev 'Error'
141149
return $Message
142150
}

0 commit comments

Comments
 (0)