SHELL/2.4.3.ps1

$CheckId = "2.4.3"
$Title = "Ensure Microsoft Defender for Cloud Apps is enabled and configured"
$Level = "L2"
$BenchmarkType = "Automated"

function Get-PropValue {
    param(
        [AllowNull()]$Object,
        [string]$Name
    )

    if ($null -eq $Object) { return $null }

    if ($Object -is [hashtable]) {
        foreach ($Key in $Object.Keys) {
            if ([string]$Key -ieq $Name) { return $Object[$Key] }
        }
    }

    if ($Object.PSObject -and $Object.PSObject.Properties) {
        foreach ($Property in $Object.PSObject.Properties) {
            if ([string]$Property.Name -ieq $Name) { return $Property.Value }
        }
    }

    return $null
}

try {
    # 1. Check Microsoft Defender for Cloud Apps license
    $DefenderCloudApps = (Get-MgSubscribedSku).ServicePlans | Where-Object {
        $_.ServicePlanName -match "CloudAppSecurity"
    }

    $CloudAppsEnabled = $false
    if ($DefenderCloudApps -and ($DefenderCloudApps.ProvisioningStatus -eq "Success")) {
        $CloudAppsEnabled = $true
        $DefenderCloudAppsStatus = "ENABLED"
    } else {
        $DefenderCloudAppsStatus = "NOT ENABLED"
    }

    # 2. Check connected services for Cloud Discovery
    $ConnectedServices = @()
    try {
        $CloudDiscoveryConnections = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/security/cloudAppSecurity/connectors" -Method GET
        $ConnectValues = Get-PropValue -Object $CloudDiscoveryConnections -Name "value"

        foreach ($Conn in $ConnectValues) {
            $ServiceName = Get-PropValue -Object $Conn -Name "serviceName"
            $Status = Get-PropValue -Object $Conn -Name "status"
            $ConnectedServices += [pscustomobject]@{
                ServiceName = $ServiceName
                Status = $Status
            }
        }
    } catch {
        $ConnectedServices = @()
    }

    $M365Connected = $ConnectedServices | Where-Object { $_.ServiceName -match "Microsoft 365" -and $_.Status -eq "Connected" }
    $AzureConnected = $ConnectedServices | Where-Object { $_.ServiceName -match "Microsoft Azure" -and $_.Status -eq "Connected" }

    $ConnectionsPass = ($M365Connected -and $AzureConnected) -ne $null

    # 3. Check Microsoft Defender for Endpoint integration
    try {
        $DefenderEndpointIntegration = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/security/cloudAppSecurity/settings" -Method GET
        $IntegrationStatus = Get-PropValue -Object $DefenderEndpointIntegration -Name "defenderForEndpointIntegrationEnabled"
    } catch {
        $IntegrationStatus = $false
    }

    # 4. Check Information Protection file monitoring
    try {
        $InfoProtectionSettings = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/security/informationProtection/settings" -Method GET
        $FileMonitoringEnabled = Get-PropValue -Object $InfoProtectionSettings -Name "enableFileMonitoring"
    } catch {
        $FileMonitoringEnabled = $false
    }

    # Evaluate compliance
    $Pass = $CloudAppsEnabled -and $ConnectionsPass -and $IntegrationStatus -and $FileMonitoringEnabled
    $Status = if ($Pass) { "PASS" } else { "FAIL" }

    [pscustomobject]@{
        CheckId = $CheckId
        Title = $Title
        Level = $Level
        BenchmarkType = $BenchmarkType
        Status = $Status
        Pass = $Pass
        Evidence = [pscustomobject]@{
            DefenderCloudAppsStatus = $DefenderCloudAppsStatus
            ConnectedServices = $ConnectedServices
            DefenderEndpointIntegrationEnabled = $IntegrationStatus
            FileMonitoringEnabled = $FileMonitoringEnabled
            SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1"
        }
        Error = if ($Pass) { $null } else { "One or more checks failed: Cloud Apps license, connected services, Defender for Endpoint integration, or file monitoring." }
        Timestamp = Get-Date
    }

} catch {
    [pscustomobject]@{
        CheckId = $CheckId
        Title = $Title
        Level = $Level
        BenchmarkType = $BenchmarkType
        Status = "ERROR"
        Pass = $null
        Evidence = [pscustomobject]@{
            SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1"
        }
        Error = $_.Exception.Message
        Timestamp = Get-Date
    }
}