public/cisa/exchange/Test-MtCisaDkim.ps1

<#
.SYNOPSIS
    Checks state of DKIM for all EXO domains

.DESCRIPTION
    DKIM SHOULD be enabled for all domains.

.EXAMPLE
    Test-MtCisaDkim

    Returns true if DKIM record exists and EXO shows DKIM enabled

.LINK
    https://maester.dev/docs/commands/Test-MtCisaDkim
#>

function Test-MtCisaDkim {
    [CmdletBinding()]
    [OutputType([bool])]
    param(
        # Selector-name for the DKIM record to test..
        [string]$Selector = "selector1"
    )

    if (!(Test-MtConnection ExchangeOnline)) {
        Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
        return $null
    }

    try {
        $dkimSigningConfigs = Get-MtExo -Request DkimSigningConfig
        $acceptedDomains = Get-MtExo -Request AcceptedDomain
        <# DKIM record without key for parked domains
        $sendingDomains = $acceptedDomains | Where-Object {`
            -not $_.SendingFromDomainDisabled
        }
        #>


        $dkimRecords = @()
        foreach ($domain in $acceptedDomains) {
            $dkimSigningConfig = $dkimSigningConfigs | Where-Object {`
                    $_.domain -eq $domain.domainname
            }
            if ((Get-Date) -gt $dkimSigningConfig.RotateOnDate) {
                if ($Selector -ne $dkimSigningConfig.SelectorAfterRotateOnDate) {
                    Write-Verbose "Using DKIM $($dkimSigningConfig.SelectorAfterRotateOnDate) based on EXO config"
                }
                $Selector = $dkimSigningConfig.SelectorAfterRotateOnDate
            } else {
                if ($Selector -ne $dkimSigningConfig.SelectorBeforeRotateOnDate) {
                    Write-Verbose "Using DKIM $($dkimSigningConfig.SelectorBeforeRotateOnDate) based on EXO config"
                }
                $selector = $dkimSigningConfig.SelectorBeforeRotateOnDate
            }

            $isMicrosoftDomain = $domain.DomainName.EndsWith(".onmicrosoft.com")
            $dkimDnsName = if ($isMicrosoftDomain) {
                $dkimSigningConfig."$($selector)CNAME"
            } else {
                "$($Selector)._domainkey.$($domain.DomainName)"
            }
            $dkimRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -DkimDnsName $dkimDnsName -Records DKIM
            $dkimRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed"
            $dkimRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value ""

            if ($domain.SendingFromDomainDisabled) {
                $dkimRecord.pass = 'Skipped'
                $dkimRecord.reason = 'Parked domain'
            } elseif (-not $dkimSigningConfig.enabled) {
                $dkimRecord.pass = 'Failed'
                $dkimRecord.reason = 'DKIM is disabled'
            } elseif ($dkimRecord.dkimRecord.GetType().Name -eq 'DKIMRecord') {
                if (-not $dkimRecord.dkimRecord.validBase64) {
                    $dkimRecord.reason = 'Malformed public key'
                } else {
                    $dkimRecord.pass = 'Passed'
                }
            } elseif ($dkimRecord.dkimRecord -like "*not available") {
                $dkimRecord.pass = "Skipped"
                $dkimRecord.reason = $dkimRecord.dkimRecord
            } else {
                $dkimRecord.reason = $dkimRecord.dkimRecord
            }

            $dkimRecords += $dkimRecord
        }
    } catch {
        Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_
        return $null
    }

    if ("Failed" -in $dkimRecords.pass) {
        $testResult = $false
    } elseif ("Failed" -notin $dkimRecords.pass -and "Passed" -notin $dkimRecords.pass) {
        Add-MtTestResultDetail -SkippedBecause NotSupported
        return $null
    } else {
        $testResult = $true
    }

    $portalLink = "https://security.microsoft.com/authentication?viewid=DKIM"

    if ($testResult) {
        $testResultMarkdown = "Well done. Your tenant's domains have DKIM configured and valid records exist.`n`n%TestResult%"
    } else {
        $testResultMarkdown = "Your tenant's domains do not have DKIM fully deployed. Review [EXO configuration]($portalLink) and DNS records.`n`n%TestResult%"
    }

    $passResult = "✅ Pass"
    $failResult = "❌ Fail"
    $skipResult = "🗄️ Skip"
    $result = "| Domain | Result | Reason |`n"
    $result += "| --- | --- | --- |`n"
    foreach ($item in $dkimRecords | Sort-Object -Property domain) {
        switch ($item.pass) {
            "Passed" { $itemResult = $passResult }
            "Skipped" { $itemResult = $skipResult }
            "Failed" { $itemResult = $failResult }
        }
        $result += "| $($item.domain) | $($itemResult) | $($item.reason) |`n"
    }

    $testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $result

    Add-MtTestResultDetail -Result $testResultMarkdown

    return $testResult
}