diff --git a/Config/standards.json b/Config/standards.json index 0feef69292203..52630842cdce3 100644 --- a/Config/standards.json +++ b/Config/standards.json @@ -5120,6 +5120,7 @@ }, { "name": "standards.SPDirectSharing", + "deprecated": true, "cat": "SharePoint Standards", "tag": [], "helpText": "This standard has been deprecated in favor of the Default Sharing Link standard. ", @@ -6580,7 +6581,7 @@ "label": "Conditional Access Template", "cat": "Templates", "multiple": true, - "disabledFeatures": { "report": true, "warn": true, "remediate": false }, + "disabledFeatures": { "report": false, "warn": false, "remediate": false }, "impact": "High Impact", "addedDate": "2023-12-30", "tag": [ @@ -8093,7 +8094,7 @@ "tag": ["CIS M365 7.0.0 (5.2.3.8)", "CIS M365 7.0.0 (5.2.3.9)"], "appliesToTest": ["CIS_5_2_3_8", "CIS_5_2_3_9"], "helpText": "**Requires Entra ID P1.** Configures the Entra ID Smart Lockout settings including lockout duration, lockout threshold, and on-premises integration mode.", - "docsDescription": "Configures the Entra ID Smart Lockout policy which protects against brute-force password attacks. Smart Lockout locks out bad actors who try to guess user passwords or use brute-force methods. It recognizes sign-ins from valid users and treats them differently from attackers. Settings include lockout duration (seconds), lockout threshold (failed attempts before lockout), and on-premises password protection mode (Audit or Enforced).", + "docsDescription": "Configures the Entra ID Smart Lockout policy which protects against brute-force password attacks. Smart Lockout locks out bad actors who try to guess user passwords or use brute-force methods. It recognizes sign-ins from valid users and treats them differently from attackers. Settings include lockout duration (seconds), lockout threshold (failed attempts before lockout), and on-premises password protection mode (Audit or Enforce).", "addedComponent": [ { "type": "number", @@ -8120,7 +8121,7 @@ "label": "On-Premises Mode", "options": [ { "label": "Audit", "value": "Audit" }, - { "label": "Enforced", "value": "Enforced" } + { "label": "Enforce", "value": "Enforce" } ] } ], diff --git a/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 b/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index aa9ede0c285b8..d38c25f56144a 100644 --- a/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 +++ b/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -59,7 +59,7 @@ function Invoke-CIPPStandardRetentionPolicyTag { } $CurrentAgeLimitForRetention = if ($CurrentState.AgeLimitForRetention) { - ([timespan]$CurrentState.AgeLimitForRetention).TotalDays + [int]([timespan]$CurrentState.AgeLimitForRetention).TotalDays } $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and diff --git a/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardSmartLockout.ps1 b/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardSmartLockout.ps1 index 8c6237bcc290c..ba687cf031ea5 100644 --- a/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardSmartLockout.ps1 +++ b/Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardSmartLockout.ps1 @@ -8,7 +8,7 @@ function Invoke-CIPPStandardSmartLockout { (Label) Configure Entra ID Smart Lockout .DESCRIPTION (Helptext) **Requires Entra ID P1.** Configures the Entra ID Smart Lockout settings including lockout duration, lockout threshold, and on-premises integration mode. - (DocsDescription) Configures the Entra ID Smart Lockout policy which protects against brute-force password attacks. Smart Lockout locks out bad actors who try to guess user passwords or use brute-force methods. It recognizes sign-ins from valid users and treats them differently from attackers. Settings include lockout duration (seconds), lockout threshold (failed attempts before lockout), and on-premises password protection mode (Audit or Enforced). + (DocsDescription) Configures the Entra ID Smart Lockout policy which protects against brute-force password attacks. Smart Lockout locks out bad actors who try to guess user passwords or use brute-force methods. It recognizes sign-ins from valid users and treats them differently from attackers. Settings include lockout duration (seconds), lockout threshold (failed attempts before lockout), and on-premises password protection mode (Audit or Enforce). .NOTES CAT Entra (AAD) Standards @@ -19,7 +19,7 @@ function Invoke-CIPPStandardSmartLockout { {"type":"number","name":"standards.SmartLockout.LockoutDurationInSeconds","label":"Lockout Duration (seconds)","default":60,"required":true} {"type":"number","name":"standards.SmartLockout.LockoutThreshold","label":"Lockout Threshold (failed attempts)","default":10,"required":true} {"type":"switch","name":"standards.SmartLockout.EnableBannedPasswordCheckOnPremises","label":"Enable On-Premises Password Protection"} - {"type":"radio","name":"standards.SmartLockout.BannedPasswordCheckOnPremisesMode","label":"On-Premises Mode","options":[{"label":"Audit","value":"Audit"},{"label":"Enforced","value":"Enforced"}]} + {"type":"radio","name":"standards.SmartLockout.BannedPasswordCheckOnPremisesMode","label":"On-Premises Mode","options":[{"label":"Audit","value":"Audit"},{"label":"Enforce","value":"Enforce"}]} IMPACT Medium Impact ADDEDDATE @@ -51,7 +51,13 @@ function Invoke-CIPPStandardSmartLockout { $DesiredLockoutDuration = [string]($Settings.LockoutDurationInSeconds.value ?? $Settings.LockoutDurationInSeconds ?? '60') $DesiredLockoutThreshold = [string]($Settings.LockoutThreshold.value ?? $Settings.LockoutThreshold ?? '10') $DesiredEnableOnPrem = [string]($Settings.EnableBannedPasswordCheckOnPremises.value ?? $Settings.EnableBannedPasswordCheckOnPremises ?? 'False') - $DesiredOnPremMode = $Settings.BannedPasswordCheckOnPremisesMode.value ?? $Settings.BannedPasswordCheckOnPremisesMode ?? 'Audit' + $DesiredOnPremMode = [string]($Settings.BannedPasswordCheckOnPremisesMode.value ?? $Settings.BannedPasswordCheckOnPremisesMode ?? 'Audit') + + # Graph only accepts 'Audit' or 'Enforce'. Templates saved before the option value was + # corrected hold 'Enforced', which never matches the tenant and reports as non-compliant. + if ($DesiredOnPremMode -eq 'Enforced') { + $DesiredOnPremMode = 'Enforce' + } # Normalize boolean switch to string if ($DesiredEnableOnPrem -eq $true -or $DesiredEnableOnPrem -eq 'true' -or $DesiredEnableOnPrem -eq 'True') { diff --git a/Modules/CIPPTests/Public/Tests/CISA/Identity/Invoke-CippTestCISAMSEXO141.ps1 b/Modules/CIPPTests/Public/Tests/CISA/Identity/Invoke-CippTestCISAMSEXO141.ps1 index b4968c25a793a..e8117ad8db535 100644 --- a/Modules/CIPPTests/Public/Tests/CISA/Identity/Invoke-CippTestCISAMSEXO141.ps1 +++ b/Modules/CIPPTests/Public/Tests/CISA/Identity/Invoke-CippTestCISAMSEXO141.ps1 @@ -33,7 +33,7 @@ function Invoke-CippTestCISAMSEXO141 { $null = $Result.Append("| Policy Name | Current Action | Expected |`n") $null = $Result.Append("| :---------- | :------------- | :------- |`n") foreach ($Policy in $FailedPolicies) { - $null = $Result.Append("| $($Policy.'Policy Name') | $($Policy.'Current Action') | $($Policy.Expected) |`n") + $null = $Result.Append("| $($Policy.Name) | $($Policy.HighConfidenceSpamAction) | Quarantine |`n") } $Status = 'Failed' } diff --git a/Modules/CIPPTests/Public/Tests/ORCA/Identity/Invoke-CippTestORCA121.ps1 b/Modules/CIPPTests/Public/Tests/ORCA/Identity/Invoke-CippTestORCA121.ps1 index d18f29b16a7c0..e95e5c5f9a378 100644 --- a/Modules/CIPPTests/Public/Tests/ORCA/Identity/Invoke-CippTestORCA121.ps1 +++ b/Modules/CIPPTests/Public/Tests/ORCA/Identity/Invoke-CippTestORCA121.ps1 @@ -2,20 +2,62 @@ function Invoke-CippTestORCA121 { <# .SYNOPSIS Supported filter policy action used + + .DESCRIPTION + ORCA121 (area: Zero Hour Autopurge). ZAP can only act on a message that was delivered to the + Junk Email folder or quarantined, so it is inert when a policy's spam or phish action is one + that leaves the message in place (e.g. AddXHeader, ModifySubject, NoAction). This checks that + SpamAction and PhishSpamAction on each anti-spam policy are actions ZAP supports. + + .FUNCTIONALITY + Internal #> param($Tenant) try { - $Policies = Get-CIPPTestData -TenantFilter $Tenant -Type 'ExoQuarantinePolicy' + $Policies = Get-CIPPTestData -TenantFilter $Tenant -Type 'ExoHostedContentFilterPolicy' if (-not $Policies) { Add-CippTestResult -TenantFilter $Tenant -TestId 'ORCA121' -TestType 'Identity' -Status 'Skipped' -ResultMarkdown 'No data found in database. This may be due to missing required licenses or data collection not yet completed.' -Risk 'Low' -Name 'Supported filter policy action used' -UserImpact 'Medium' -ImplementationEffort 'Low' -Category 'Quarantine' return } - $Status = 'Passed' - $Result = [System.Text.StringBuilder]::new("Quarantine policies are configured to support Zero Hour Auto Purge.`n`n") - $null = $Result.Append("**Total Policies:** $($Policies.Count)") + # Actions ZAP can act on, per ORCA121. Anything else leaves the message in the inbox, + # where ZAP has nothing to purge. + $SupportedActions = @('MoveToJmf', 'Redirect', 'Delete', 'Quarantine') + + $Failures = [System.Collections.Generic.List[object]]::new() + $PolicyCount = 0 + + foreach ($Policy in $Policies) { + $PolicyCount++ + # ORCA evaluates the two actions as separate config items, so a policy can fail on + # one and pass on the other; report them independently rather than per-policy. + foreach ($Setting in @('SpamAction', 'PhishSpamAction')) { + $Value = $Policy.$Setting + if ($Value -notin $SupportedActions) { + $Failures.Add([PSCustomObject]@{ + Policy = $Policy.Identity ?? $Policy.Name + Setting = $Setting + Value = if ($null -eq $Value -or $Value -eq '') { 'Not set' } else { $Value } + }) | Out-Null + } + } + } + + if ($Failures.Count -eq 0) { + $Status = 'Passed' + $Result = [System.Text.StringBuilder]::new("✅ **Pass**: All $PolicyCount anti-spam policy/policies use a filter action that Zero Hour Auto Purge supports.`n`n") + $null = $Result.Append("Supported actions: $($SupportedActions -join ', ').") + } else { + $Status = 'Failed' + $Result = [System.Text.StringBuilder]::new("❌ **Fail**: $($Failures.Count) setting(s) across $PolicyCount anti-spam policy/policies use an action that Zero Hour Auto Purge cannot act on:`n`n") + $null = $Result.Append("| Policy | Setting | Current Action | Supported |`n") + $null = $Result.Append("| :----- | :------ | :------------- | :-------- |`n") + foreach ($Failure in $Failures) { + $null = $Result.Append("| $($Failure.Policy) | $($Failure.Setting) | $($Failure.Value) | $($SupportedActions -join ', ') |`n") + } + } Add-CippTestResult -TenantFilter $Tenant -TestId 'ORCA121' -TestType 'Identity' -Status $Status -ResultMarkdown $Result -Risk 'Low' -Name 'Supported filter policy action used' -UserImpact 'Medium' -ImplementationEffort 'Low' -Category 'Quarantine'