Security/Get-ComplianceSecurityConfig.ps1
|
<#
.SYNOPSIS Collects Microsoft Purview/Compliance security configuration settings for M365 assessment. .DESCRIPTION Queries Security & Compliance PowerShell for compliance-related security settings including unified audit log, DLP policies, and sensitivity labels. Returns a structured inventory of settings with current values and CIS benchmark recommendations. Requires an active Security & Compliance (Purview) connection. .PARAMETER OutputPath Optional path to export results as CSV. If not specified, results are returned to the pipeline. .EXAMPLE PS> . .\Common\Connect-Service.ps1 PS> Connect-Service -Service Purview PS> .\Security\Get-ComplianceSecurityConfig.ps1 Displays Purview/Compliance security configuration settings. .EXAMPLE PS> .\Security\Get-ComplianceSecurityConfig.ps1 -OutputPath '.\compliance-security-config.csv' Exports the security configuration to CSV. .NOTES Author: Daren9m Settings checked are aligned with CIS Microsoft 365 Foundations Benchmark v6.0.1 recommendations. #> [CmdletBinding()] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$OutputPath ) # Stop on errors: API failures should halt this collector rather than produce partial results. $ErrorActionPreference = 'Stop' # Load shared security-config helpers $_scriptDir = if ($MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { $PSScriptRoot } . (Join-Path -Path $_scriptDir -ChildPath '..\Common\SecurityConfigHelper.ps1') $ctx = Initialize-SecurityConfig $settings = $ctx.Settings $checkIdCounter = $ctx.CheckIdCounter function Add-Setting { param( [string]$Category, [string]$Setting, [string]$CurrentValue, [string]$RecommendedValue, [string]$Status, [string]$CheckId = '', [string]$Remediation = '' ) $p = @{ Settings = $settings CheckIdCounter = $checkIdCounter Category = $Category Setting = $Setting CurrentValue = $CurrentValue RecommendedValue = $RecommendedValue Status = $Status CheckId = $CheckId Remediation = $Remediation } Add-SecuritySetting @p } # ------------------------------------------------------------------ # 1. Unified Audit Log (CIS 3.1.1) # ------------------------------------------------------------------ try { Write-Verbose "Checking unified audit log configuration..." $auditLogAvailable = Get-Command -Name Get-AdminAuditLogConfig -ErrorAction SilentlyContinue if ($auditLogAvailable) { $auditConfig = Get-AdminAuditLogConfig -ErrorAction Stop $auditEnabled = $auditConfig.UnifiedAuditLogIngestionEnabled $settingParams = @{ Category = 'Audit' Setting = 'Unified Audit Log Ingestion' CurrentValue = "$auditEnabled" RecommendedValue = 'True' Status = if ($auditEnabled) { 'Pass' } else { 'Fail' } CheckId = 'COMPLIANCE-AUDIT-001' Remediation = 'Run: Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true. Microsoft Purview > Audit > Start recording user and admin activity.' } Add-Setting @settingParams } else { $settingParams = @{ Category = 'Audit' Setting = 'Unified Audit Log Ingestion' CurrentValue = 'Cmdlet not available' RecommendedValue = 'True' Status = 'Review' CheckId = 'COMPLIANCE-AUDIT-001' Remediation = 'Connect to Security & Compliance PowerShell to check audit log configuration.' } Add-Setting @settingParams } } catch { Write-Warning "Could not check unified audit log: $_" } # ------------------------------------------------------------------ # 2. DLP Policies Exist (CIS 3.2.1) # ------------------------------------------------------------------ try { Write-Verbose "Checking DLP policies..." $dlpAvailable = Get-Command -Name Get-DlpCompliancePolicy -ErrorAction SilentlyContinue if ($dlpAvailable) { $dlpPolicies = Get-DlpCompliancePolicy -ErrorAction Stop $enabledPolicies = @($dlpPolicies | Where-Object { $_.Enabled -eq $true }) if ($enabledPolicies.Count -gt 0) { $settingParams = @{ Category = 'Data Loss Prevention' Setting = 'DLP Policies' CurrentValue = "$($enabledPolicies.Count) enabled (of $(@($dlpPolicies).Count) total)" RecommendedValue = 'At least 1 enabled' Status = 'Pass' CheckId = 'COMPLIANCE-DLP-001' Remediation = 'No action needed.' } Add-Setting @settingParams } else { $settingParams = @{ Category = 'Data Loss Prevention' Setting = 'DLP Policies' CurrentValue = $(if (@($dlpPolicies).Count -eq 0) { 'None configured' } else { "$(@($dlpPolicies).Count) policies (none enabled)" }) RecommendedValue = 'At least 1 enabled' Status = 'Fail' CheckId = 'COMPLIANCE-DLP-001' Remediation = 'Microsoft Purview > Data loss prevention > Policies > Create a DLP policy covering sensitive information types relevant to your organization.' } Add-Setting @settingParams } # CIS 3.2.2 -- DLP covers Teams $teamsPolicies = @($enabledPolicies | Where-Object { $_.TeamsLocation -or ($_.Workload -and $_.Workload -match 'Teams') }) if ($teamsPolicies.Count -gt 0) { $settingParams = @{ Category = 'Data Loss Prevention' Setting = 'DLP Covers Teams' CurrentValue = "$($teamsPolicies.Count) policies include Teams" RecommendedValue = 'At least 1 policy covers Teams' Status = 'Pass' CheckId = 'COMPLIANCE-DLP-002' Remediation = 'No action needed.' } Add-Setting @settingParams } else { $settingParams = @{ Category = 'Data Loss Prevention' Setting = 'DLP Covers Teams' CurrentValue = 'No DLP policies cover Teams' RecommendedValue = 'At least 1 policy covers Teams' Status = 'Fail' CheckId = 'COMPLIANCE-DLP-002' Remediation = 'Microsoft Purview > Data loss prevention > Policies > Edit an existing policy or create new > Include Teams chat and channel messages location.' } Add-Setting @settingParams } } else { $settingParams = @{ Category = 'Data Loss Prevention' Setting = 'DLP Policies' CurrentValue = 'Cmdlet not available' RecommendedValue = 'At least 1 enabled' Status = 'Review' CheckId = 'COMPLIANCE-DLP-001' Remediation = 'Connect to Security & Compliance PowerShell to check DLP policies.' } Add-Setting @settingParams } } catch { Write-Warning "Could not check DLP policies: $_" } # ------------------------------------------------------------------ # 3. Sensitivity Labels Published (CIS 3.3.1) # ------------------------------------------------------------------ try { Write-Verbose "Checking sensitivity label policies..." $labelAvailable = Get-Command -Name Get-LabelPolicy -ErrorAction SilentlyContinue if ($labelAvailable) { $labelPolicies = Get-LabelPolicy -ErrorAction Stop if (@($labelPolicies).Count -gt 0) { $settingParams = @{ Category = 'Information Protection' Setting = 'Sensitivity Label Policies' CurrentValue = "$(@($labelPolicies).Count) policies published" RecommendedValue = 'At least 1 published' Status = 'Pass' CheckId = 'COMPLIANCE-LABELS-001' Remediation = 'No action needed.' } Add-Setting @settingParams } else { $settingParams = @{ Category = 'Information Protection' Setting = 'Sensitivity Label Policies' CurrentValue = 'None published' RecommendedValue = 'At least 1 published' Status = 'Fail' CheckId = 'COMPLIANCE-LABELS-001' Remediation = 'Microsoft Purview > Information protection > Labels > Create and publish sensitivity labels. Then create a label policy to deploy them to users.' } Add-Setting @settingParams } } else { $settingParams = @{ Category = 'Information Protection' Setting = 'Sensitivity Label Policies' CurrentValue = 'Cmdlet not available' RecommendedValue = 'At least 1 published' Status = 'Review' CheckId = 'COMPLIANCE-LABELS-001' Remediation = 'Connect to Security & Compliance PowerShell to check sensitivity labels.' } Add-Setting @settingParams } } catch { Write-Warning "Could not check sensitivity labels: $_" } # ------------------------------------------------------------------ # Output # ------------------------------------------------------------------ Export-SecurityConfigReport -Settings $settings -OutputPath $OutputPath -ServiceLabel 'Compliance' |