Private/Audit/Invoke-DeviceManagementChecks.ps1

# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0
# https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/
# AI/LLM use: see AI-USAGE.md for required attribution
function Invoke-DeviceManagementChecks {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$AuditData,

        [string]$OrgUnitPath = '/'
    )

    $checkDefs = Get-AuditCategoryDefinitions -Category 'DeviceManagementChecks'
    $findings = [System.Collections.Generic.List[PSCustomObject]]::new()

    foreach ($check in $checkDefs.checks) {
        $funcName = "Test-Fortification$($check.id -replace '-', '')"
        if (Get-Command $funcName -ErrorAction SilentlyContinue) {
            try {
                $finding = & $funcName -AuditData $AuditData -CheckDefinition $check -OrgUnitPath $OrgUnitPath
                if ($finding) { $findings.Add($finding) }
            } catch {
                $findings.Add((New-AuditFinding -CheckDefinition $check -Status 'ERROR' `
                    -CurrentValue "Check failed: $_" -OrgUnitPath $OrgUnitPath))
            }
        } else {
            $findings.Add((New-AuditFinding -CheckDefinition $check -Status 'SKIP' `
                -CurrentValue 'Check not yet implemented' -OrgUnitPath $OrgUnitPath))
        }
    }

    return @($findings)
}

# ── DEVICE-001: MDM Policy Audit ─────────────────────────────────────────
function Test-FortificationDEVICE001 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    if (-not $AuditData.MobileDevices) {
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
            -CurrentValue 'Mobile device data not available. Verify in Admin Console > Devices > Mobile devices that MDM policies are enforced' `
            -OrgUnitPath $OrgUnitPath
    }

    $devices = @($AuditData.MobileDevices)
    if ($devices.Count -eq 0) {
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'PASS' `
            -CurrentValue 'No mobile devices registered' -OrgUnitPath $OrgUnitPath
    }

    $managed = @($devices | Where-Object {
        $_.status -eq 'APPROVED' -or $_.managementType -eq 'ADVANCED' -or $_.managementType -eq 'BASIC'
    })
    $unmanaged = @($devices | Where-Object {
        $_.status -ne 'APPROVED' -and $_.managementType -ne 'ADVANCED' -and $_.managementType -ne 'BASIC'
    })

    $managedRate = if ($devices.Count -gt 0) { [Math]::Round(($managed.Count / $devices.Count) * 100, 1) } else { 0 }

    $status = if ($managedRate -ge 95) { 'PASS' }
              elseif ($managedRate -ge 75) { 'WARN' }
              else { 'FAIL' }

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status $status `
        -CurrentValue "$managedRate% ($($managed.Count) of $($devices.Count)) devices under MDM management" `
        -OrgUnitPath $OrgUnitPath `
        -Details @{
            TotalDevices   = $devices.Count
            ManagedCount   = $managed.Count
            UnmanagedCount = $unmanaged.Count
            ManagedRate    = $managedRate
        }
}

# ── DEVICE-002: Device Approval Requirements ─────────────────────────────
function Test-FortificationDEVICE002 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    # Device approval settings are OU-level policies not exposed via the Admin SDK directory API
    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Device approval requirements not available via API. Verify in Admin Console > Devices > Mobile & endpoints > Settings that admin approval is required for device access' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Requiring device approval prevents unauthorized devices from accessing organizational data' }
}

# ── DEVICE-003: Screen Lock Enforcement ──────────────────────────────────
function Test-FortificationDEVICE003 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Screen lock enforcement settings not available via API. Verify in Admin Console > Devices > Mobile & endpoints > Settings > Universal settings that screen lock is enforced' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Screen lock should be enforced with minimum PIN/password complexity to prevent unauthorized physical access' }
}

# ── DEVICE-004: Device Encryption Requirements ───────────────────────────
function Test-FortificationDEVICE004 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Device encryption requirements not available via API. Verify in Admin Console > Devices > Mobile & endpoints > Settings that device encryption is required' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Encryption protects data at rest on devices in case of physical theft or loss' }
}

# ── DEVICE-005: Compromised Device Blocking ──────────────────────────────
function Test-FortificationDEVICE005 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Compromised device blocking settings not available via API. Verify in Admin Console > Devices > Mobile & endpoints > Settings that compromised devices are blocked' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Compromised device detection should automatically block access to organizational data' }
}

# ── DEVICE-006: Jailbroken/Rooted Device Policy ─────────────────────────
function Test-FortificationDEVICE006 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Jailbroken/rooted device policy not available via API. Verify in Admin Console > Devices > Mobile & endpoints > Settings that jailbroken/rooted devices are blocked' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Jailbroken (iOS) or rooted (Android) devices bypass OS security controls and should not access organizational data' }
}

# ── DEVICE-007: Chrome Browser Management ────────────────────────────────
function Test-FortificationDEVICE007 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    if ($AuditData.ChromePolicies) {
        $policies = $AuditData.ChromePolicies
        $policyCount = if ($policies -is [array]) { $policies.Count }
                       elseif ($policies -is [hashtable]) { $policies.Keys.Count }
                       else { 0 }

        $status = if ($policyCount -gt 0) { 'PASS' } else { 'WARN' }
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status $status `
            -CurrentValue "$policyCount Chrome browser policy setting(s) configured" `
            -OrgUnitPath $OrgUnitPath `
            -Details @{ PolicyCount = $policyCount }
    }

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Chrome browser policy data not available. Verify in Admin Console > Devices > Chrome > Settings that browser management policies are configured' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Chrome Browser Cloud Management provides centralized policy enforcement for managed browsers' }
}

# ── DEVICE-008: Chrome Extension Whitelist/Blocklist ─────────────────────
function Test-FortificationDEVICE008 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    # Chrome extension policies are part of Chrome Browser Cloud Management
    if ($AuditData.ChromePolicies) {
        $policies = $AuditData.ChromePolicies
        # Look for extension-related policies
        $extensionPolicy = $null
        if ($policies -is [hashtable]) {
            $extensionPolicy = $policies['ExtensionInstallBlocklist'] ?? $policies['ExtensionInstallAllowlist'] ??
                               $policies['ExtensionInstallForcelist']
        }

        if ($extensionPolicy) {
            return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'PASS' `
                -CurrentValue 'Chrome extension management policies are configured' `
                -OrgUnitPath $OrgUnitPath `
                -Details @{ Note = 'Extension allowlist/blocklist policies detected' }
        }
    }

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Chrome extension policy data not available. Verify in Admin Console > Devices > Chrome > Apps & extensions that extension installation is restricted via allowlist' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Malicious extensions can steal credentials, exfiltrate data, and intercept browsing activity' }
}

# ── DEVICE-009: Chrome OS Device Policies ────────────────────────────────
function Test-FortificationDEVICE009 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    if (-not $AuditData.ChromeDevices) {
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
            -CurrentValue 'Chrome OS device data not available. Verify in Admin Console > Devices > Chrome > Devices that Chrome OS devices are managed' `
            -OrgUnitPath $OrgUnitPath
    }

    $devices = @($AuditData.ChromeDevices)
    if ($devices.Count -eq 0) {
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'PASS' `
            -CurrentValue 'No Chrome OS devices registered' -OrgUnitPath $OrgUnitPath
    }

    $active = @($devices | Where-Object { $_.status -eq 'ACTIVE' })
    $deprovisioned = @($devices | Where-Object { $_.status -eq 'DEPROVISIONED' })
    $disabled = @($devices | Where-Object { $_.status -eq 'DISABLED' })

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'PASS' `
        -CurrentValue "$($devices.Count) Chrome OS device(s): $($active.Count) active, $($deprovisioned.Count) deprovisioned, $($disabled.Count) disabled" `
        -OrgUnitPath $OrgUnitPath `
        -Details @{
            TotalDevices       = $devices.Count
            ActiveCount        = $active.Count
            DeprovisionedCount = $deprovisioned.Count
            DisabledCount      = $disabled.Count
        }
}

# ── DEVICE-010: Endpoint Verification Settings ───────────────────────────
function Test-FortificationDEVICE010 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
        -CurrentValue 'Endpoint verification settings not available via API. Verify in Admin Console > Devices > Settings that endpoint verification is enabled for context-aware access' `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ Note = 'Endpoint verification provides device trust signals used by context-aware access policies' }
}

# ── DEVICE-011: Company-Owned Device Inventory ───────────────────────────
function Test-FortificationDEVICE011 {
    [CmdletBinding()]
    param([hashtable]$AuditData, [hashtable]$CheckDefinition, [string]$OrgUnitPath = '/')

    $totalDevices = 0
    $deviceBreakdown = @{}

    if ($AuditData.MobileDevices) {
        $mobileCount = @($AuditData.MobileDevices).Count
        $totalDevices += $mobileCount
        $deviceBreakdown['MobileDevices'] = $mobileCount
    }

    if ($AuditData.ChromeDevices) {
        $chromeCount = @($AuditData.ChromeDevices).Count
        $totalDevices += $chromeCount
        $deviceBreakdown['ChromeOSDevices'] = $chromeCount
    }

    if ($totalDevices -eq 0 -and -not $AuditData.MobileDevices -and -not $AuditData.ChromeDevices) {
        return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'WARN' `
            -CurrentValue 'Device inventory data not available. Verify in Admin Console > Devices that company-owned devices are registered and tracked' `
            -OrgUnitPath $OrgUnitPath
    }

    $breakdownStr = @($deviceBreakdown.GetEnumerator() | ForEach-Object { "$($_.Key): $($_.Value)" }) -join ', '

    return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'PASS' `
        -CurrentValue "$totalDevices managed device(s) in inventory ($breakdownStr)" `
        -OrgUnitPath $OrgUnitPath `
        -Details @{ TotalDevices = $totalDevices; Breakdown = $deviceBreakdown }
}