Public/Get-NLBaselineCACISCompliance.ps1

function Get-NLBaselineCACISCompliance {
    <#
    .SYNOPSIS
    Validate Conditional Access policies against CIS Microsoft 365 Foundations Benchmark
     
    .DESCRIPTION
    Analyzes all Conditional Access policies and validates compliance with CIS Microsoft 365 Foundations Benchmark controls.
    Provides detailed reporting on which CIS controls are met and which are missing.
     
    .EXAMPLE
    Get-NLBaselineCACISCompliance
    #>

    
    [CmdletBinding()]
    param()
    
    try {
        # Check connection
        $context = Get-MgContext -ErrorAction SilentlyContinue
        if (-not $context -or -not $context.TenantId) {
            Write-Host "Not connected to Microsoft 365. Connecting..." -ForegroundColor Yellow
            Write-Host ""
            $connection = Connect-NLBaselineCA
            if (-not $connection) {
                Write-Error "Cannot connect to Microsoft 365"
                return
            }
            $context = Get-MgContext
        }
        
        Write-Host "========================================" -ForegroundColor Cyan
        Write-Host " CIS COMPLIANCE VALIDATION" -ForegroundColor Cyan
        Write-Host "========================================" -ForegroundColor Cyan
        Write-Host ""
        Write-Host "CIS Microsoft 365 Foundations Benchmark v6.0.0" -ForegroundColor Yellow
        Write-Host ""
        
        # Get all policies using helper function with REST API fallback
        Write-Host "Retrieving Conditional Access policies..." -ForegroundColor Gray
        $policies = Get-AllConditionalAccessPolicies
        
        if (-not $policies -or $policies.Count -eq 0) {
            Write-Error "Failed to retrieve Conditional Access policies or no policies found"
            return
        }
        
        Write-Host "Found $($policies.Count) policies to analyze" -ForegroundColor Green
        Write-Host ""
        
        # CIS Benchmark Controls for Conditional Access
        $cisControls = @{
            "1.1.1" = @{
                Description = "Ensure MFA is enabled for all users"
                Required = $true
                Policies = @()
                Met = $false
            }
            "1.1.2" = @{
                Description = "Ensure users can register security methods securely"
                Required = $true
                Policies = @()
                Met = $false
            }
            "1.1.3" = @{
                Description = "Ensure MFA is required for administrative roles"
                Required = $true
                Policies = @()
                Met = $false
            }
            "1.1.4" = @{
                Description = "Ensure legacy authentication is blocked"
                Required = $true
                Policies = @()
                Met = $false
            }
            "1.1.5" = @{
                Description = "Enable Identity Protection policies"
                Required = $false
                Policies = @()
                Met = $false
            }
            "1.2.1" = @{
                Description = "Restrict access by location/IP"
                Required = $false
                Policies = @()
                Met = $false
            }
            "1.2.2" = @{
                Description = "Admin session controls"
                Required = $true
                Policies = @()
                Met = $false
            }
            "2.1.1" = @{
                Description = "Modern authentication required"
                Required = $true
                Policies = @()
                Met = $false
            }
            "2.1.2" = @{
                Description = "Device management required"
                Required = $true
                Policies = @()
                Met = $false
            }
            "2.1.3" = @{
                Description = "Device compliance policies"
                Required = $true
                Policies = @()
                Met = $false
            }
            "3.1.1" = @{
                Description = "Guest MFA required"
                Required = $true
                Policies = @()
                Met = $false
            }
            "3.1.2" = @{
                Description = "Guest access restrictions"
                Required = $true
                Policies = @()
                Met = $false
            }
            "3.1.3" = @{
                Description = "Guest session controls"
                Required = $true
                Policies = @()
                Met = $false
            }
            "6.1.1" = @{
                Description = "Geographic restrictions"
                Required = $false
                Policies = @()
                Met = $false
            }
        }
        
        # Analyze each policy
        Write-Host "Analyzing policies against CIS controls..." -ForegroundColor Gray
        Write-Host ""
        
        foreach ($policy in $policies) {
            $policyName = $policy.DisplayName
            $state = $policy.State
            
            # Skip disabled policies
            if ($state -eq "disabled") {
                continue
            }
            
            # Check 1.1.1 - MFA for all users
            if ($policy.GrantControls.BuiltInControls -contains "mfa" -or 
                $policy.GrantControls.AuthenticationStrength -ne $null) {
                if ($policy.Conditions.Users.IncludeUsers -contains "All" -or 
                    $policy.Conditions.Users.IncludeUsers.Count -gt 100) {
                    $cisControls["1.1.1"].Policies += $policyName
                    $cisControls["1.1.1"].Met = $true
                }
            }
            
            # Check 1.1.2 - Secure registration
            if ($policy.Conditions.Applications.IncludeUserActions -contains "urn:user:registersecurityinfo" -or
                $policy.Conditions.Applications.IncludeUserActions -contains "microsoft.graph.security.securityInfoRegistration") {
                if ($policy.GrantControls.BuiltInControls -contains "mfa" -or
                    $policy.Conditions.Locations.IncludeLocations -contains "AllTrustedLocations") {
                    $cisControls["1.1.2"].Policies += $policyName
                    $cisControls["1.1.2"].Met = $true
                }
            }
            
            # Check 1.1.3 - MFA for admin roles
            if ($policy.GrantControls.BuiltInControls -contains "mfa" -or 
                $policy.GrantControls.AuthenticationStrength -ne $null) {
                if ($policy.Conditions.Users.IncludeRoles.Count -gt 0) {
                    $cisControls["1.1.3"].Policies += $policyName
                    $cisControls["1.1.3"].Met = $true
                }
            }
            
            # Check 1.1.4 - Block legacy auth
            if ($policy.Conditions.ClientAppTypes -contains "exchangeActiveSync" -or
                $policy.Conditions.ClientAppTypes -contains "other") {
                if ($policy.GrantControls.BuiltInControls -contains "block") {
                    $cisControls["1.1.4"].Policies += $policyName
                    $cisControls["1.1.4"].Met = $true
                }
            }
            
            # Check 1.1.5 - Identity Protection
            if ($policy.Conditions.SignInRiskLevels.Count -gt 0 -or
                $policy.Conditions.UserRiskLevels.Count -gt 0) {
                $cisControls["1.1.5"].Policies += $policyName
                $cisControls["1.1.5"].Met = $true
            }
            
            # Check 1.2.1 - Location restrictions
            if ($policy.Conditions.Locations.ExcludeLocations.Count -gt 0 -or
                $policy.Conditions.Locations.IncludeLocations.Count -gt 0) {
                $cisControls["1.2.1"].Policies += $policyName
                $cisControls["1.2.1"].Met = $true
            }
            
            # Check 1.2.2 - Admin session controls
            if ($policy.Conditions.Users.IncludeRoles.Count -gt 0) {
                if ($policy.SessionControls.SignInFrequency -ne $null -or
                    $policy.SessionControls.PersistentBrowser -ne $null -or
                    $policy.SessionControls.CloudAppSecurity -ne $null) {
                    $cisControls["1.2.2"].Policies += $policyName
                    $cisControls["1.2.2"].Met = $true
                }
            }
            
            # Check 2.1.1 - Modern auth required
            if ($policy.Conditions.ClientAppTypes -notcontains "exchangeActiveSync" -and
                $policy.Conditions.ClientAppTypes -notcontains "other") {
                if ($policy.GrantControls.BuiltInControls -contains "mfa" -or
                    $policy.GrantControls.BuiltInControls -contains "compliantDevice") {
                    $cisControls["2.1.1"].Policies += $policyName
                    $cisControls["2.1.1"].Met = $true
                }
            }
            
            # Check 2.1.2 - Device management
            if ($policy.GrantControls.BuiltInControls -contains "compliantDevice" -or
                $policy.GrantControls.BuiltInControls -contains "domainJoinedDevice" -or
                $policy.GrantControls.BuiltInControls -contains "approvedApplication") {
                $cisControls["2.1.2"].Policies += $policyName
                $cisControls["2.1.2"].Met = $true
            }
            
            # Check 2.1.3 - Device compliance
            if ($policy.GrantControls.BuiltInControls -contains "compliantDevice" -or
                $policy.SessionControls.CloudAppSecurity -ne $null) {
                $cisControls["2.1.3"].Policies += $policyName
                $cisControls["2.1.3"].Met = $true
            }
            
            # Check 3.1.1 - Guest MFA
            if ($policy.Conditions.Users.IncludeGuestsOrExternalUsers -ne $null) {
                if ($policy.GrantControls.BuiltInControls -contains "mfa" -or
                    $policy.GrantControls.AuthenticationStrength -ne $null) {
                    $cisControls["3.1.1"].Policies += $policyName
                    $cisControls["3.1.1"].Met = $true
                }
            }
            
            # Check 3.1.2 - Guest restrictions
            if ($policy.Conditions.Users.IncludeGuestsOrExternalUsers -ne $null) {
                if ($policy.Conditions.Applications.IncludeApplications.Count -lt 10 -or
                    $policy.GrantControls.BuiltInControls -contains "block") {
                    $cisControls["3.1.2"].Policies += $policyName
                    $cisControls["3.1.2"].Met = $true
                }
            }
            
            # Check 3.1.3 - Guest session controls
            if ($policy.Conditions.Users.IncludeGuestsOrExternalUsers -ne $null) {
                if ($policy.SessionControls.SignInFrequency -ne $null -or
                    $policy.SessionControls.PersistentBrowser -ne $null) {
                    $cisControls["3.1.3"].Policies += $policyName
                    $cisControls["3.1.3"].Met = $true
                }
            }
            
            # Check 6.1.1 - Geographic restrictions
            if ($policy.Conditions.Locations.ExcludeLocations.Count -gt 0) {
                $cisControls["6.1.1"].Policies += $policyName
                $cisControls["6.1.1"].Met = $true
            }
        }
        
        # Calculate compliance score
        $requiredControls = $cisControls.Values | Where-Object { $_.Required -eq $true }
        $metRequired = ($requiredControls | Where-Object { $_.Met -eq $true }).Count
        $totalRequired = $requiredControls.Count
        $complianceScore = [math]::Round(($metRequired / $totalRequired) * 100, 2)
        
        # Display results
        Write-Host "========================================" -ForegroundColor Green
        Write-Host " COMPLIANCE RESULTS" -ForegroundColor Green
        Write-Host "========================================" -ForegroundColor Green
        Write-Host ""
        Write-Host "Overall Compliance Score: $complianceScore%" -ForegroundColor $(if ($complianceScore -ge 90) { "Green" } elseif ($complianceScore -ge 70) { "Yellow" } else { "Red" })
        Write-Host "Required Controls Met: $metRequired / $totalRequired" -ForegroundColor White
        Write-Host ""
        
        Write-Host "CIS Control Status:" -ForegroundColor Cyan
        Write-Host ""
        
        foreach ($controlId in ($cisControls.Keys | Sort-Object)) {
            $control = $cisControls[$controlId]
            $status = if ($control.Met) { "✅ MET" } else { "❌ NOT MET" }
            $color = if ($control.Met) { "Green" } else { $(if ($control.Required) { "Red" } else { "Yellow" }) }
            
            Write-Host " $controlId - $($control.Description)" -ForegroundColor White
            Write-Host " Status: $status" -ForegroundColor $color
            if ($control.Policies.Count -gt 0) {
                Write-Host " Policies: $($control.Policies.Count)" -ForegroundColor Gray
                foreach ($policyName in $control.Policies) {
                    Write-Host " - $policyName" -ForegroundColor DarkGray
                }
            }
            Write-Host ""
        }
        
        # Save report
        $moduleConfigPath = Get-ConfigPath
        if (Test-Path $moduleConfigPath) {
            $moduleConfig = Get-Content $moduleConfigPath | ConvertFrom-Json
            $storagePath = $moduleConfig.StoragePath
            
            if (Test-Path $storagePath) {
                $reportPath = Join-Path $storagePath "CISCompliance"
                if (-not (Test-Path $reportPath)) {
                    New-Item -Path $reportPath -ItemType Directory -Force | Out-Null
                }
                
                $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
                $reportFile = Join-Path $reportPath "cis-compliance-$timestamp.json"
                $reportFileCsv = Join-Path $reportPath "cis-compliance-$timestamp.csv"
                
                # Prepare report data
                $reportData = @{
                    AnalysisDate = (Get-Date).ToString("o")
                    CISBenchmark = "Microsoft 365 Foundations Benchmark v6.0.0"
                    ComplianceScore = $complianceScore
                    RequiredControlsMet = $metRequired
                    TotalRequiredControls = $totalRequired
                    TotalPoliciesAnalyzed = $policies.Count
                    Controls = @()
                }
                
                foreach ($controlId in $cisControls.Keys) {
                    $control = $cisControls[$controlId]
                    $reportData.Controls += [PSCustomObject]@{
                        ControlId = $controlId
                        Description = $control.Description
                        Required = $control.Required
                        Met = $control.Met
                        PolicyCount = $control.Policies.Count
                        Policies = $control.Policies
                    }
                }
                
                $reportData | ConvertTo-Json -Depth 10 | Out-File -FilePath $reportFile -Encoding UTF8
                
                # CSV export
                $reportData.Controls | Export-Csv -Path $reportFileCsv -NoTypeInformation -Encoding UTF8
                
                Write-Host "========================================" -ForegroundColor Green
                Write-Host " REPORT SAVED" -ForegroundColor Green
                Write-Host "========================================" -ForegroundColor Green
                Write-Host "JSON report: $reportFile" -ForegroundColor White
                Write-Host "CSV report: $reportFileCsv" -ForegroundColor White
                Write-Host ""
            }
        }
        
        return $reportData
    }
    catch {
        Write-Error "Error validating CIS compliance: $_"
    }
}