Private/Get-AACDefenderQuery.ps1

function Get-AACDefenderQuery {
    <#
    .SYNOPSIS
        The Azure Resource Graph queries for Microsoft Defender for Cloud
        (securityresources) - one set, shared by Get-AACInventory and
        Get-AACSecurityPosture, so both read the same data the same way.
    .DESCRIPTION
        -Name picks the queries, by name, into an ordered hashtable for
        Invoke-AACGraphBatch:
          Scores each subscription's secure score (ascScore)
          Controls the secure score controls, with points
          ControlAssessments which recommendation (assessment key) is in
                                 which control
          Summary per resource: healthy and unhealthy
                                 assessments, unhealthy ones by severity
          Recommendations every unhealthy assessment: resource,
                                 recommendation, severity, impact, effort,
                                 categories, cause, description, remediation
                                 steps, portal link, since when
          Alerts active and in-progress security alerts
          Plans the Defender plans (pricings), on or off
          Standards regulatory compliance standards
          ComplianceControls their controls
          ComplianceAssessments the assessments in each control
          PolicyStates every policy state (Get-AACPolicyStateQuery),
                                 rolled up as the portal does by
                                 ConvertTo-AACPolicyState
          PolicyAssignments the assignments' display names and scopes
                                 (read tenant-wide: many are at management
                                 group scope)
    #>

    [CmdletBinding()]
    [OutputType([System.Collections.Specialized.OrderedDictionary])]
    param(
        [Parameter(Mandatory)]
        [ValidateSet('Scores', 'Controls', 'ControlAssessments', 'Summary', 'Recommendations', 'Alerts', 'Plans', 'Standards', 'ComplianceControls', 'ComplianceAssessments', 'PolicyStates', 'PolicyAssignments')]
        [string[]] $Name
    )

    $assessments = "securityresources | where type =~ 'microsoft.security/assessments' | extend resourceId = tolower(coalesce(tostring(properties.resourceDetails.Id), tostring(properties.resourceDetails.ResourceId))), status = tostring(properties.status.code), severity = tostring(properties.metadata.severity)"
    $all = [ordered]@{
        Scores                = "securityresources | where type =~ 'microsoft.security/securescores' and name == 'ascScore' | project subscriptionId, current = todouble(properties.score.current), max = todouble(properties.score.max)"
        Controls              = "securityresources | where type =~ 'microsoft.security/securescores/securescorecontrols' | project subscriptionId, control = tostring(properties.displayName), current = todouble(properties.score.current), max = todouble(properties.score.max), healthy = toint(properties.healthyResourceCount), unhealthy = toint(properties.unhealthyResourceCount)"
        ControlAssessments    = "securityresources | where type =~ 'microsoft.security/securescores/securescorecontrols' | mv-expand definition = properties.definition.properties.assessmentDefinitions | project control = tostring(properties.displayName), key = tolower(tostring(split(tostring(definition.id), '/')[-1])) | where isnotempty(key) | distinct control, key"
        Summary               = "$assessments | where status in ('Healthy', 'Unhealthy') | summarize healthy = countif(status == 'Healthy'), unhealthy = countif(status == 'Unhealthy'), high = countif(status == 'Unhealthy' and severity == 'High'), medium = countif(status == 'Unhealthy' and severity == 'Medium'), low = countif(status == 'Unhealthy' and severity == 'Low') by resourceId"
        Recommendations       = "$assessments | where status == 'Unhealthy' | project key = tolower(name), resourceId, subscriptionId, name = tostring(properties.displayName), severity, impact = tostring(properties.metadata.userImpact), effort = tostring(properties.metadata.implementationEffort), categories = strcat_array(properties.metadata.categories, ', '), cause = tostring(properties.status.cause), description = tostring(properties.metadata.description), remediation = tostring(properties.metadata.remediationDescription), link = tostring(properties.links.azurePortal), since = tostring(properties.status.statusChangeDate)"
        Alerts                = "securityresources | where type =~ 'microsoft.security/locations/alerts' | extend status = tostring(coalesce(properties.Status, properties.status)) | where status in~ ('Active', 'InProgress') | project id, subscriptionId, status, name = tostring(coalesce(properties.AlertDisplayName, properties.alertDisplayName)), severity = tostring(coalesce(properties.Severity, properties.severity)), intent = tostring(coalesce(properties.Intent, properties.intent)), alertType = tostring(coalesce(properties.AlertType, properties.alertType)), time = tostring(coalesce(properties.TimeGeneratedUtc, properties.timeGeneratedUtc)), description = tostring(coalesce(properties.Description, properties.description)), link = tostring(coalesce(properties.AlertUri, properties.alertUri)), entity = tostring(coalesce(properties.CompromisedEntity, properties.compromisedEntity)), resources = coalesce(properties.ResourceIdentifiers, properties.resourceIdentifiers)"
        Plans                 = "securityresources | where type =~ 'microsoft.security/pricings' | where properties.deprecated != true | project subscriptionId, plan = name, tier = tostring(properties.pricingTier), subPlan = tostring(properties.subPlan)"
        Standards             = "securityresources | where type =~ 'microsoft.security/regulatorycompliancestandards' | project subscriptionId, standard = name, state = tostring(properties.state), passed = toint(properties.passedControls), failed = toint(properties.failedControls), skipped = toint(properties.skippedControls), unsupported = toint(properties.unsupportedControls)"
        ComplianceControls    = "securityresources | where type =~ 'microsoft.security/regulatorycompliancestandards/regulatorycompliancecontrols' | extend standard = extract('(?i)/regulatoryComplianceStandards/([^/]+)', 1, id) | project subscriptionId, standard, control = name, description = tostring(properties.description), state = tostring(properties.state), passed = toint(properties.passedAssessments), failed = toint(properties.failedAssessments), skipped = toint(properties.skippedAssessments)"
        ComplianceAssessments = "securityresources | where type =~ 'microsoft.security/regulatorycompliancestandards/regulatorycompliancecontrols/regulatorycomplianceassessments' | extend standard = extract('(?i)/regulatoryComplianceStandards/([^/]+)', 1, id), control = extract('(?i)/regulatoryComplianceControls/([^/]+)', 1, id) | project subscriptionId, standard, control, key = tolower(name), description = tostring(properties.description), state = tostring(properties.state), failedResources = toint(properties.failedResources)"
        PolicyStates          = Get-AACPolicyStateQuery
        PolicyAssignments     = "policyresources | where type =~ 'microsoft.authorization/policyassignments' | project assignmentId = tolower(id), name, displayName = tostring(properties.displayName), scope = tostring(properties.scope), enforcement = tostring(properties.enforcementMode)"
    }
    $picked = [ordered]@{}
    foreach ($key in $Name) { $picked[$key] = $all[$key] }
    $picked
}