Skip to content

Commit 5f43d86

Browse files
committed
Added function for Custom Quarantine Policies
1 parent 1efed26 commit 5f43d86

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
function Invoke-CIPPStandardQuarantineTemplate {
2+
<#
3+
.FUNCTIONALITY
4+
Internal
5+
.COMPONENT
6+
(APIName) QuarantineTemplate
7+
.SYNOPSIS
8+
(Label) Custom Quarantine Policy
9+
.DESCRIPTION
10+
(Helptext) This standard creates a Custom Quarantine Policies that can be used in Anti-Spam and all MDO365 policies. Quarantine Policies can be used to specify recipients permissions, enable end-user spam notifications, and specify the release action preference
11+
(DocsDescription) This standard creates a Custom Quarantine Policies that can be used in Anti-Spam and all MDO365 policies. Quarantine Policies can be used to specify recipients permissions, enable end-user spam notifications, and specify the release action preference
12+
.NOTES
13+
CAT
14+
Defender Standards
15+
DISABLEDFEATURES
16+
{"report":false,"warn":false,"remediate":false}
17+
TAG
18+
ADDEDCOMPONENT
19+
{"type":"autoComplete","multiple":false,"creatable":true,"name":"displayName","label":"Quarantine Display Name","required":true}
20+
{"type":"switch","label":"Enable end-user spam notifications","name":"ESNEnabled","defaultValue":true,"required":false}
21+
{"type":"select","multiple":false,"label":"Select release action preference","name":"ReleaseAction","options":[{"label":"Allow recipients to request a message to be released from quarantine","value":"PermissionToRequestRelease"},{"label":"Allow recipients to release a message from quarantine","value":"PermissionToRelease"}]}
22+
{"type":"switch","label":"Include Messages From Blocked Sender Address","name":"IncludeMessagesFromBlockedSenderAddress","defaultValue":false,"required":false}
23+
{"type":"switch","label":"Allow recipients to delete message","name":"PermissionToDelete","defaultValue":false,"required":false}
24+
{"type":"switch","label":"Allow recipients to preview message","name":"PermissionToPreview","defaultValue":false,"required":false}
25+
{"type":"switch","label":"Allow recipients to block Sender Address","name":"PermissionToBlockSender","defaultValue":false,"required":false}
26+
{"type":"switch","label":"Allow recipients to whitelist Sender Address","name":"PermissionToAllowSender","defaultValue":false,"required":false}
27+
MULTIPLE
28+
True
29+
IMPACT
30+
Low Impact
31+
ADDEDDATE
32+
2025-05-16
33+
POWERSHELLEQUIVALENT
34+
Set-QuarantinePolicy or New-QuarantinePolicy
35+
RECOMMENDEDBY
36+
UPDATECOMMENTBLOCK
37+
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
38+
.LINK
39+
https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact
40+
#>
41+
42+
param($Tenant, $Settings)
43+
44+
45+
function Convert-HashtableToEndUserQuarantinePermissionsValue {
46+
param (
47+
[hashtable]$InputHashtable
48+
)
49+
#Converts hashtable with selected end user quarantine permissions to decimal value used by EndUserQuarantinePermissionsValue property in New-QuarantinePolicy and Set-QuarantinePolicy
50+
try {
51+
$EndUserQuarantinePermissionsValue = 0
52+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToViewHeader * 128
53+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToDownload * 64
54+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToAllowSender * 32
55+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToBlockSender * 16
56+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToRequestRelease * 8
57+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToRelease * 4
58+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToPreview * 2
59+
$EndUserQuarantinePermissionsValue += [int]$InputHashtable.PermissionToDelete * 1
60+
return $EndUserQuarantinePermissionsValue
61+
}
62+
catch {
63+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
64+
throw "Convert-HashtableToEndUserQuarantinePermissionsValue: Failed to hashtable QuarantinePermissionsValue. Error: $ErrorMessage"
65+
}
66+
}
67+
68+
function Convert-StringToHashtable {
69+
param (
70+
[string]$InputString
71+
)
72+
#Converts string value with EndUserQuarantinePermissions received from Get-QuarantinePolicy
73+
try {
74+
# Remove square brackets and split into lines
75+
$InputString = $InputString.Trim('[', ']')
76+
$hashtable = @{}
77+
$InputString -split "`n" | ForEach-Object {
78+
$key, $value = $_ -split ":\s*"
79+
$hashtable[$key.Trim()] = [System.Convert]::ToBoolean($value.Trim())
80+
}
81+
return $hashtable
82+
}
83+
catch {
84+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
85+
throw "Convert-StringToHashtable: Failed to convert string to hashtable. Error: $ErrorMessage"
86+
}
87+
}
88+
89+
try {
90+
# Get the current custom quarantine policies
91+
$CurrentPolicies = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-QuarantinePolicy' | Where-Object -Property Guid -ne '00000000-0000-0000-0000-000000000000' -ErrorAction Stop
92+
93+
# Compare the settings from standard with the current policies
94+
$CompareList = foreach ($Policy in $Settings) {
95+
try {
96+
# prepare the cmdParams used in New-ExoRequest
97+
$cmdParams = @{
98+
ESNEnabled = $Policy.ESNEnabled
99+
IncludeMessagesFromBlockedSenderAddress = $Policy.IncludeMessagesFromBlockedSenderAddress
100+
}
101+
102+
# Create hashtable with desired EndUserQuarantinePermissions
103+
$EndUserQuarantinePermissions = @{
104+
PermissionToBlockSender = $Policy.PermissionToBlockSender
105+
PermissionToDelete = $Policy.PermissionToDelete
106+
PermissionToDownload = $false
107+
PermissionToPreview = $Policy.PermissionToPreview
108+
PermissionToRelease = if ($Policy.ReleaseAction -eq "PermissionToRelease") { $true } else { $false }
109+
PermissionToRequestRelease = if ($Policy.ReleaseAction -eq "PermissionToRequestRelease") { $true } else { $false }
110+
PermissionToViewHeader = $true
111+
PermissionToAllowSender = $Policy.PermissionToAllowSender
112+
}
113+
114+
# If the Quarantine Policy already exists
115+
if ($Policy.displayName.value -in $CurrentPolicies.Name) {
116+
#Get the current policy and convert EndUserQuarantinePermissions from string to hashtable for compare
117+
$ExistingPolicy = $CurrentPolicies | Where-Object -Property Name -eq $Policy.displayName.value
118+
$ExistingPolicyEndUserQuarantinePermissions = Convert-StringToHashtable -InputString $ExistingPolicy.EndUserQuarantinePermissions -ErrorAction Stop
119+
120+
#Compare the current policy
121+
$StateIsCorrect = ($ExistingPolicy.Name -eq $Policy.displayName.value) -and
122+
($ExistingPolicy.ESNEnabled -eq $Policy.ESNEnabled) -and
123+
($ExistingPolicy.IncludeMessagesFromBlockedSenderAddress -eq $Policy.IncludeMessagesFromBlockedSenderAddress) -and
124+
(!(Compare-Object @($ExistingPolicyEndUserQuarantinePermissions.values) @($EndUserQuarantinePermissions.values)))
125+
126+
# If the current policy is correct
127+
if ($StateIsCorrect -eq $true) {
128+
[PSCustomObject]@{
129+
missing = $false
130+
StateIsCorrect = $StateIsCorrect
131+
displayName = $Policy.displayName.value
132+
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
133+
cmdParams = $cmdParams
134+
remediate = $Policy.remediate
135+
alert = $Policy.alert
136+
report = $Policy.report
137+
}
138+
}
139+
#If the current policy doesn't match the desired settings
140+
else {
141+
[PSCustomObject]@{
142+
missing = $false
143+
StateIsCorrect = $StateIsCorrect
144+
displayName = $Policy.displayName.value
145+
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
146+
cmdParams = $cmdParams
147+
remediate = $Policy.remediate
148+
alert = $Policy.alert
149+
report = $Policy.report
150+
}
151+
}
152+
}
153+
#If no existing Quarantine Policy with the same name was found
154+
else {
155+
[PSCustomObject]@{
156+
missing = $true
157+
StateIsCorrect = $false
158+
displayName = $Policy.displayName.value
159+
EndUserQuarantinePermissions = $EndUserQuarantinePermissions
160+
cmdParams = $cmdParams
161+
remediate = $Policy.remediate
162+
alert = $Policy.alert
163+
report = $Policy.report
164+
}
165+
}
166+
}
167+
catch {
168+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
169+
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to compare Quarantine policy $($Policy.displayName.value), Error: $ErrorMessage" -sev 'Error'
170+
}
171+
}
172+
173+
174+
If ($true -in $Settings.remediate) {
175+
# Remediate each policy which is incorrect or missing
176+
foreach ($Policy in $CompareList | Where-Object { $_.remediate -EQ $true -and $_.StateIsCorrect -eq $false }) {
177+
try {
178+
# Convert desired EndUserQuarantinePermissions to decimal value
179+
$EndUserQuarantinePermissionsValue = Convert-HashtableToEndUserQuarantinePermissionsValue -InputHashtable $Policy.EndUserQuarantinePermissions -ErrorAction Stop
180+
$cmdParams = $Policy.cmdParams
181+
182+
# Create policy if missing
183+
if ($Policy.missing) {
184+
try {
185+
#Add the rest of the desired settings to cmdParams
186+
$cmdParams.Add('Name', $Policy.displayName)
187+
$cmdParams.Add('EndUserQuarantinePermissionsValue', $EndUserQuarantinePermissionsValue)
188+
189+
New-ExoRequest -tenantid $Tenant -cmdlet 'New-QuarantinePolicy' -cmdParams $cmdParams -UseSystemMailbox $true -ErrorAction Stop
190+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Custom Quarantine Policy $($Policy.displayName)" -sev Info
191+
}
192+
catch {
193+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
194+
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create Quarantine policy $($Policy.displayName), Error: $ErrorMessage" -sev 'Error'
195+
}
196+
}
197+
# Update policy if incorrect
198+
else {
199+
try {
200+
#Add the rest of the desired settings to cmdParams
201+
$cmdParams.Add('Identity', $Policy.displayName)
202+
$cmdParams.Add('EndUserQuarantinePermissionsValue', $EndUserQuarantinePermissionsValue)
203+
204+
New-ExoRequest -tenantid $Tenant -cmdlet 'Set-QuarantinePolicy' -cmdParams $cmdParams -UseSystemMailbox $true -ErrorAction Stop
205+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Custom Quarantine Policy $($Policy.displayName)" -sev Info
206+
}
207+
catch {
208+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Custom Quarantine Policy $($Policy.displayName)" -sev Error -LogData $_
209+
}
210+
}
211+
}
212+
catch {
213+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
214+
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Quarantine policy $($Policy.displayName), Error: $ErrorMessage" -sev 'Error'
215+
}
216+
}
217+
}
218+
219+
if ($true -in $Settings.alert) {
220+
foreach ($Policy in $CompareList | Where-Object -Property alert -EQ $true) {
221+
if ($Policy.StateIsCorrect) {
222+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Quarantine policy $($Policy.displayName) has the correct configuration." -sev Info
223+
}
224+
else {
225+
if ($Policy.missing) {
226+
$CurrentInfo = $Policy | Select-Object -Property displayName, missing
227+
Write-StandardsAlert -message "Quarantine policy $($Policy.displayName) is missing." -object $CurrentInfo -tenant $Tenant -standardName 'QuarantineTemplate' -standardId $Settings.templateId
228+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Quarantine policy $($Policy.displayName) is missing." -sev info
229+
}
230+
else {
231+
$CurrentInfo = $CurrentPolicies | Where-Object -Property Name -eq $Policy.displayName | Select-Object -Property Name, ESNEnabled, IncludeMessagesFromBlockedSenderAddress, EndUserQuarantinePermissions
232+
Write-StandardsAlert -message "Quarantine policy $($Policy.displayName) does not match the expected configuration." -object $CurrentInfo -tenant $Tenant -standardName 'QuarantineTemplate' -standardId $Settings.templateId
233+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Quarantine policy $($Policy.displayName) does not match the expected configuration. We've generated an alert" -sev info
234+
}
235+
}
236+
}
237+
}
238+
239+
if ($true -in $Settings.report) {
240+
# This could do with an improvement. But will work for now or else reporting could be disabled for now
241+
foreach ($Policy in $CompareList | Where-Object -Property report -EQ $true) {
242+
Set-CIPPStandardsCompareField -FieldName "standards.QuarantineTemplate" -FieldValue $Policy.StateIsCorrect -TenantFilter $Tenant
243+
}
244+
}
245+
}
246+
catch {
247+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
248+
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Quarantine policy/policies, Error: $ErrorMessage" -sev 'Error'
249+
}
250+
}

0 commit comments

Comments
 (0)