Rules/CA-004.no-stale-report-only.psd1

@{
    Id          = 'CA-004'
    Title       = 'No Conditional Access policy is stuck in report-only mode'
    Area        = 'ConditionalAccess'
    Severity    = 'Low'
    References  = @(
        'https://learn.microsoft.com/entra/identity/conditional-access/concept-conditional-access-report-only'
    )
    Rationale   = 'Report-only is a rollout tool, not a destination. A policy in report-only mode for more than 30 days protects nothing while suggesting it does.'
    Remediation = 'Review the report-only policy results and either enable or delete the policy.'
    Test        = {
        param($Snapshot)
        $threshold = [DateTime]::UtcNow.AddDays(-30)
        $stale = @($Snapshot.ConditionalAccess | Where-Object {
                $_.state -eq 'enabledForReportingButNotEnforced'
            } | Where-Object {
                $reference = $null
                if ($_.PSObject.Properties['modifiedDateTime'] -and $_.modifiedDateTime) { $reference = [DateTime]$_.modifiedDateTime }
                elseif ($_.PSObject.Properties['createdDateTime'] -and $_.createdDateTime) { $reference = [DateTime]$_.createdDateTime }
                ($null -ne $reference) -and ($reference.ToUniversalTime() -lt $threshold)
            })
        if ($stale.Count -gt 0) {
            New-TLRuleResult -Status Fail -Evidence @($stale | ForEach-Object { "$($_.displayName) (report-only since $($_.modifiedDateTime))" })
        }
        else {
            New-TLRuleResult -Status Pass -Evidence 'No policy has been in report-only mode for more than 30 days.'
        }
    }
}