tests/Test-Assessment.41059.ps1

<#
.SYNOPSIS
    EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus.
 
.DESCRIPTION
    Validates the Microsoft Defender for Endpoint "Enable EDR in block mode" Secure Score
    recommendation via Microsoft Secure Score.
 
    EDR in block mode adds Microsoft Defender for Endpoint blocking when Microsoft Defender
    Antivirus is running in passive mode alongside a non-Microsoft antivirus solution.
    Malicious artifacts that the third-party antivirus misses may not be remediated without it.
 
    The check reads the Secure Score control profile for scid_2004 and the latest per-control
    score snapshot, then returns:
      Pass – EDR in block mode is enabled.
      Fail – EDR in block mode is disabled or the Secure Score control is ignored.
      Investigate – The control profile or Secure Score snapshot could not be located.
      Investigate – Microsoft Graph returned HTTP 401 or 403 (insufficient permissions).
 
.NOTES
    Test ID: 41059
    Workshop Task: SECOPS-059
    Pillar: SecOps
    Category: Endpoint threat protection
    Risk Level: High
    Supported Clouds: Global, USGov, USGovDoD
    Required Permission: SecurityEvents.Read.All (Application or Delegated)
#>


function Test-Assessment-41059 {
    [ZtTest(
        Category = 'Endpoint threat protection',
        CompatibleLicense = ('WINDEFATP'),
        ImplementationCost = 'Low',
        Pillar = 'SecOps',
        RiskLevel = 'High',
        Service = ('Graph'),
        SfiPillar = 'Monitor and detect cyberthreats',
        TenantType = ('Workforce'),
        TestId = 41059,
        Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus',
        UserImpact = 'Low'
    )]
    [CmdletBinding()]
    param()

    #region Data Collection

    Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
    $activity  = 'Checking EDR in block mode Secure Score control'
    $controlId = 'scid_2004'
    Write-ZtProgress -Activity $activity -Status 'Retrieving EDR in block mode Secure Score control profile'

    # Q1 – Retrieve the pinned MDATP "Enable EDR in block mode" control profile.
    # An empty result set indicates the profile is absent from this tenant's Secure Score.
    $controlProfile = $null
    $errorMsgQ1     = $null
    $httpStatusQ1   = $null

    try {
        $profileResults = Invoke-ZtGraphRequest -RelativeUri 'security/secureScoreControlProfiles' -Filter "service eq 'MDATP' and id eq '$controlId'" -ApiVersion beta -ErrorAction Stop
        $controlProfile = $profileResults | Select-Object -First 1
    }
    catch {
        $errorMsgQ1   = $_
        $httpStatusQ1 = Get-ZtHttpStatusCode -ErrorRecord $_
        Write-PSFMessage "Failed to retrieve EDR in block mode control profile: $errorMsgQ1" -Level Warning
    }

    # Q2 – Retrieve the most recent Secure Score snapshot (only if Q1 succeeded).
    $latestSecureScore = $null
    $errorMsgQ2        = $null

    if ($null -ne $controlProfile) {
        Write-ZtProgress -Activity $activity -Status 'Retrieving latest Microsoft Secure Score'
        try {
            $scoreResponse     = Invoke-ZtGraphRequest -RelativeUri 'security/secureScores' -Top 1 -ApiVersion beta -DisablePaging -ErrorAction Stop
            $latestSecureScore = $scoreResponse.value | Select-Object -First 1
        }
        catch {
            $errorMsgQ2 = $_
            Write-PSFMessage "Failed to retrieve Secure Score snapshot: $errorMsgQ2" -Level Warning
        }
    }

    #endregion Data Collection

    #region Assessment Logic

    $passed       = $false
    $customStatus = $null

    # ── Q1 failed: 401/403, unexpected error, or missing profile → Investigate ──
    if ($null -eq $controlProfile) {
        if ($httpStatusQ1 -in @(401, 403)) {
            $investigateReason = 'The **SecurityEvents.Read.All** permission is required to read Secure Score control profiles. Verify the permission is consented and re-run the assessment.'
        }
        elseif ($null -ne $errorMsgQ1) {
            $investigateReason = 'Microsoft Graph returned an unexpected error retrieving the EDR in block mode Secure Score control profile. Re-run the assessment in 5–10 minutes and verify **SecurityEvents.Read.All** is consented.'
        }
        else {
            $investigateReason = 'The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
        }

        $testResultMarkdown = "⚠️ $investigateReason"
        $customStatus       = 'Investigate'

        $params = @{
            TestId       = '41059'
            Title        = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
            Status       = $passed
            Result       = $testResultMarkdown
            CustomStatus = $customStatus
        }
        Add-ZtTestResultDetail @params
        return
    }

    $profileTitle = $controlProfile.title

    # ── Investigate: Q2 failed or returned no snapshot ──
    if ($null -ne $errorMsgQ2 -or $null -eq $latestSecureScore) {
        if ($null -ne $errorMsgQ2) {
            $investigateReason = 'Microsoft Graph returned an unexpected error retrieving the latest Secure Score snapshot. Re-run the assessment in 5–10 minutes.'
        }
        else {
            $investigateReason = 'The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
        }
        $testResultMarkdown = "⚠️ $investigateReason"
        $customStatus       = 'Investigate'

        $params = @{
            TestId       = '41059'
            Title        = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
            Status       = $passed
            Result       = $testResultMarkdown
            CustomStatus = $customStatus
        }
        Add-ZtTestResultDetail @params
        return
    }

    # ── Locate the per-control entry inside controlScores[] ──
    $controlScoreEntry = $null
    if ($latestSecureScore.controlScores) {
        $controlScoreEntry = $latestSecureScore.controlScores |
            Where-Object { $_.controlName -eq $controlId } |
            Select-Object -First 1
    }

    # ── Investigate: profile exists but snapshot has no scored entry for this control,
    # or score/maxScore is null (would produce a false Pass via PowerShell $null coercion) ──
    $score    = $controlScoreEntry.score
    $maxScore = $controlProfile.maxScore

    if ($null -eq $controlScoreEntry -or $null -eq $score -or $null -eq $maxScore) {
        $testResultMarkdown = '⚠️ The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
        $customStatus       = 'Investigate'

        $params = @{
            TestId       = '41059'
            Title        = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
            Status       = $passed
            Result       = $testResultMarkdown
            CustomStatus = $customStatus
        }
        Add-ZtTestResultDetail @params
        return
    }

    # ── Determine ignored state from the most recent controlStateUpdates entry ──
    $latestStateUpdate = @($controlProfile.controlStateUpdates | Sort-Object { if ($_.updatedDateTime) { [datetime]$_.updatedDateTime } else { [datetime]::MinValue } } -Descending) | Select-Object -First 1
    $isIgnored         = $latestStateUpdate -and $latestStateUpdate.state -eq 'Ignored'

    if (($score -ge $maxScore) -and (-not $isIgnored)) {
        $passed             = $true
        $testResultMarkdown = "✅ EDR in block mode is enabled.`n`n%TestResult%"
    }
    else {
        $passed             = $false
        $testResultMarkdown = "❌ EDR in block mode is disabled or the Secure Score control is ignored.`n`n%TestResult%"
    }

    #endregion Assessment Logic

    #region Report Generation

    $secureScoreUrl = 'https://security.microsoft.com/securescore'
    $ignoredDisplay = if ($isIgnored) { '⚠️ Yes' } else { '✅ No' }
    $rowStatus      = if ($passed) { '✅ Pass' } else { '❌ Fail' }
    $lastModified   = if ($controlProfile.lastModifiedDateTime) { Get-FormattedDate -DateString $controlProfile.lastModifiedDateTime } else { '—' }

    $tableRows = "| $(Get-SafeMarkdown $profileTitle) | $controlId | $score | $maxScore | $ignoredDisplay | $lastModified | $rowStatus |`n"

    $mdTable = @"
 
 
### [Microsoft Secure Score]($secureScoreUrl)
 
| Control title | Control id | Score | Max score | Ignored | Last modified | Status |
| :------------ | :--------- | :---- | :-------- | :------ | :------------ | :----- |
$tableRows
"@


    $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdTable

    #endregion Report Generation

    $params = @{
        TestId = '41059'
        Title  = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
        Status = $passed
        Result = $testResultMarkdown
    }
    if ($customStatus) {
        $params.CustomStatus = $customStatus
    }

    Add-ZtTestResultDetail @params
}