SHELL/2.4.4.ps1
|
$CheckId = "2.4.4" $Title = "Ensure Zero-hour auto purge for Microsoft Teams is on" $Level = "L1" $BenchmarkType = "Automated" $AuditCommands = [pscustomobject]@{ TeamsProtectionPolicy = "Get-TeamsProtectionPolicy | Format-List ZapEnabled" TeamsProtectionPolicyRule = "Get-TeamsProtectionPolicyRule | Format-List ExceptIf*" } function Get-AvailableCommandName { param( [string[]]$Names ) foreach ($Name in $Names) { if (Get-Command -Name $Name -ErrorAction SilentlyContinue) { return $Name } } return $null } function Get-NonEmptyValues { param( [AllowNull()] [object]$Value ) $Values = @() foreach ($Item in @($Value)) { if ($null -eq $Item) { continue } $Text = ([string]$Item).Trim() if ([string]::IsNullOrWhiteSpace($Text)) { continue } if ($Text -eq "{}") { continue } if ($Text -eq "False") { continue } $Values += $Text } return @($Values | Select-Object -Unique) } try { $FailureReasons = [System.Collections.Generic.List[string]]::new() $ManualReasons = [System.Collections.Generic.List[string]]::new() $ErrorReasons = [System.Collections.Generic.List[string]]::new() $PolicyCmd = Get-AvailableCommandName -Names @("Get-TeamsProtectionPolicy") $RuleCmd = Get-AvailableCommandName -Names @("Get-TeamsProtectionPolicyRule") if (-not $PolicyCmd) { $ManualReasons.Add("Get-TeamsProtectionPolicy cmdlet is unavailable in the current session.") } if (-not $RuleCmd) { $ManualReasons.Add("Get-TeamsProtectionPolicyRule cmdlet is unavailable in the current session.") } $Policies = @() $Rules = @() if ($PolicyCmd) { $Policies = @(& $PolicyCmd) if (@($Policies).Count -eq 0) { $ErrorReasons.Add("Get-TeamsProtectionPolicy returned no result.") } } if ($RuleCmd) { $Rules = @(& $RuleCmd) } $PolicyZapReport = @() $ZapEnabledState = $null if (@($Policies).Count -gt 0) { $PolicyZapReport = foreach ($Policy in $Policies) { $Zap = $null if ($null -ne $Policy.PSObject.Properties['ZapEnabled']) { $Zap = [bool]$Policy.ZapEnabled } [pscustomobject]@{ Identity = [string]$Policy.Identity Name = [string]$Policy.Name ZapEnabled = $Zap } } $KnownZap = @($PolicyZapReport | Where-Object { $null -ne $_.ZapEnabled }) if (@($KnownZap).Count -eq 0) { $ManualReasons.Add("Unable to determine ZapEnabled value from Teams protection policy output.") } else { $ZapEnabledState = @($KnownZap | Where-Object { $_.ZapEnabled -eq $false }).Count -eq 0 if (-not $ZapEnabledState) { $FailureReasons.Add("ZapEnabled is not True on all returned Teams protection policies.") } } } $ExclusionFindings = @() if ($RuleCmd -and @($Rules).Count -gt 0) { foreach ($Rule in $Rules) { $ExceptProps = @($Rule.PSObject.Properties | Where-Object { $_.Name -like "ExceptIf*" }) $NonEmptyByProperty = [ordered]@{} foreach ($Prop in $ExceptProps) { $Values = Get-NonEmptyValues -Value $Prop.Value if (@($Values).Count -gt 0) { $NonEmptyByProperty[$Prop.Name] = @($Values) } } if ($NonEmptyByProperty.Count -gt 0) { $ExclusionFindings += [pscustomobject]@{ Identity = [string]$Rule.Identity Name = [string]$Rule.Name Exclusions = [pscustomobject]$NonEmptyByProperty } } } } if ($RuleCmd -and @($ExclusionFindings).Count -gt 0 -and $FailureReasons.Count -eq 0 -and $ErrorReasons.Count -eq 0) { $ManualReasons.Add("One or more Teams protection exclusions (ExceptIf*) are configured and must be manually justified per CIS guidance.") } $Status = "PASS" $Pass = $true $ErrorMessage = $null if ($ErrorReasons.Count -gt 0) { $Status = "ERROR" $Pass = $null $ErrorMessage = ($ErrorReasons -join " ") } elseif ($FailureReasons.Count -gt 0) { $Status = "FAIL" $Pass = $false $ErrorMessage = ($FailureReasons -join " ") } elseif ($ManualReasons.Count -gt 0) { $Status = "MANUAL_REVIEW" $Pass = $null $ErrorMessage = "Manual review required: $($ManualReasons -join " ")" } [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = $Status Pass = $Pass Evidence = [pscustomobject]@{ AuditCommands = $AuditCommands AuditUiReference = @( "Microsoft Defender > Settings > Email & collaboration > Microsoft Teams protection", "Ensure Zero-hour auto purge (ZAP) is On", "Review exclusions under 'Exclude these participants' and confirm they are justified" ) PolicyCommandUsed = $PolicyCmd RuleCommandUsed = $RuleCmd PolicyCount = @($Policies).Count RuleCount = @($Rules).Count PolicyZapReport = @($PolicyZapReport) ExclusionFindings = @($ExclusionFindings) ManualReviewReasons = @($ManualReasons) SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = $ErrorMessage Timestamp = Get-Date } } catch { [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = "ERROR" Pass = $null Evidence = [pscustomobject]@{ AuditCommands = $AuditCommands SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = $_.Exception.Message Timestamp = Get-Date } } |