Src/Private/Get-AbrPurviewCommunicationCompliance.ps1

function Get-AbrPurviewCommunicationCompliance {
    <#
    .SYNOPSIS
    Used by As Built Report to retrieve Microsoft Purview Communication Compliance information.
    .DESCRIPTION
        Collects and reports on Communication Compliance policies configured in
        Microsoft Purview, including supervised users and reviewers.
    .NOTES
        Version: 0.1.0
        Author: Pai Wei Sing
    .EXAMPLE

    .LINK

    #>

    [CmdletBinding()]
    param (
        [Parameter (
            Position = 0,
            Mandatory)]
        [string]
        $TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Microsoft Purview Communication Compliance information for tenant $TenantId." | Out-Null
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Communication Compliance'
    }

    process {
        try {
            $CCPolicies = Get-SupervisoryReviewPolicyV2 -ErrorAction Stop

            if ($CCPolicies) {
                Section -Style Heading2 'Communication Compliance Policies' {
                    $OutObj = [System.Collections.ArrayList]::new()

                    foreach ($Policy in $CCPolicies) {
                        try {
                             $_pre_Enabled_41 = if ($Policy.Enabled) { 'Yes' } else { 'No' }
                             $_pre_ReviewerEmails_43 = if ($Policy.ReviewerEmailAddresses) { ($Policy.ReviewerEmailAddresses -join ', ') } else { '--' }
                            $inObj = [ordered] @{
                             'Policy Name'         = $Policy.Name
                             'Enabled' = $_pre_Enabled_41
                             'Reviewers'           = ($Policy.Reviewers -join ', ')
                             'Reviewer Emails' = $_pre_ReviewerEmails_43
                             'Users'               = ($Policy.Users -join ', ')
                             'Groups'              = ($Policy.Groups -join ', ')
                             'Created'             = $Policy.WhenCreated.ToString('yyyy-MM-dd')
                             'Last Modified'       = $Policy.WhenChanged.ToString('yyyy-MM-dd')
                            }
                            $OutObj.Add([pscustomobject]$inObj) | Out-Null
                        } catch {
                            Write-PScriboMessage -IsWarning -Message "Communication Compliance Policy '$($Policy.Name)': $($_.Exception.Message)" | Out-Null
                        }
                    }

                    if ($Healthcheck -and $script:HealthCheck.Purview.CommunicationCompliance) {
                        $OutObj | Where-Object { $_.'Enabled' -eq 'No' } | Set-Style -Style Critical | Out-Null
                        # Flag policies scoped to specific users/groups rather than all users (MCCA check-CC102)
                        $OutObj | Where-Object {
                            ($_.'Users' -ne '' -and $_.'Users' -ne '--') -or
                            ($_.'Groups' -ne '' -and $_.'Groups' -ne '--')
                        } | Set-Style -Style Warning | Out-Null
                    }

                    $TableParams = @{
                        Name         = "Communication Compliance Policies - $TenantId"
                        List         = $false
                        ColumnWidths = 18, 8, 14, 16, 12, 12, 10, 10
                    }
                    if ($script:Report.ShowTableCaptions) {
                        $TableParams['Caption'] = "- $($TableParams.Name)"
                    }
                    $OutObj | Sort-Object -Property 'Policy Name' | Table @TableParams

                    #region Coverage summary and ACSC check (MCCA check-CC101 / CC102)
                    if ($script:InfoLevel.CommunicationCompliance -ge 3) {
                        $EnabledPolicies   = @($CCPolicies | Where-Object { $_.Enabled })
                        $OrgWidePolicies   = @($CCPolicies | Where-Object {
                            $_.Enabled -and
                            (-not $_.Users -or $_.Users.Count -eq 0) -and
                            (-not $_.Groups -or $_.Groups.Count -eq 0)
                        })
                        $_ccHasPolicy      = $EnabledPolicies.Count -gt 0
                        $_ccHasOrgWide     = $OrgWidePolicies.Count -gt 0

                        Write-AbrPurviewACSCCheck -TenantId $TenantId -SectionName 'Communication Compliance' -Checks @(
                            [pscustomobject]@{
                                ControlId   = 'ISM-1228'
                                E8          = 'N/A'
                                Description = 'Inappropriate and policy-violating communications detected'
                                Check       = 'At least one enabled Communication Compliance policy configured'
                                Status      = if ($_ccHasPolicy) { 'Pass' } else { 'Fail' }
                            },
                            [pscustomobject]@{
                                ControlId   = 'ISM-1228'
                                E8          = 'N/A'
                                Description = 'Communication Compliance policy covers entire organisation'
                                Check       = 'At least one policy is not scoped to specific users or groups only'
                                Status      = if ($_ccHasOrgWide) { 'Pass' } elseif ($_ccHasPolicy) { 'Partial' } else { 'Fail' }
                            }
                        )
                    }
                    #endregion

                    # Rules per policy
                    if ($script:InfoLevel.CommunicationCompliance -ge 2) {
                        foreach ($Policy in $CCPolicies) {
                                 try {
                                  $Rules = Get-SupervisoryReviewRule -Policy $Policy.Name -ErrorAction SilentlyContinue
                                  if ($Rules) {
                                   Section -ExcludeFromTOC -Style NOTOCHeading3 "Rules: $($Policy.Name)" {
                                    $RuleObj = [System.Collections.ArrayList]::new()
                                    foreach ($Rule in $Rules) {
                                     try {
                                      $ruleInObj = [ordered] @{
                                       'Rule Name'         = $Rule.Name
                                       'Sample Rate (%)'   = $Rule.SamplingRate
                                       'Condition'         = $Rule.Condition
                                       'Direction'         = $script:TextInfo.ToTitleCase($Rule.Direction)
                                      }
                                      $RuleObj.Add([pscustomobject]$ruleInObj) | Out-Null
                                     } catch {
                                      Write-PScriboMessage -IsWarning -Message "CC Rule '$($Rule.Name)': $($_.Exception.Message)" | Out-Null
                                     }
                                    }
                                    $RuleTableParams = @{
                                     Name         = "Communication Compliance Rules - $($Policy.Name)"
                                     List         = $false
                                     ColumnWidths = 28, 15, 42, 15
                                    }
                                    if ($script:Report.ShowTableCaptions) {
                                     $RuleTableParams['Caption'] = "- $($RuleTableParams.Name)"
                                    }
                                    $RuleObj | Sort-Object -Property 'Rule Name' | Table @RuleTableParams
                                   }
                                  }
                                 } catch {
                                  Write-PScriboMessage -IsWarning -Message "CC Rules for '$($Policy.Name)': $($_.Exception.Message)" | Out-Null
                                 }
                                }
                    }
                }
            } else {
                Write-PScriboMessage -Message "No Communication Compliance Policy information found for $TenantId. Disabling section." | Out-Null
            }
        } catch {
            Write-PScriboMessage -IsWarning -Message "Communication Compliance Section: $($_.Exception.Message)" | Out-Null
        }
    }

    end {
        Show-AbrDebugExecutionTime -End -TitleMessage 'Communication Compliance'
    }
}