Scripts/DlpPolicyEvaluator.ps1

<#
.SYNOPSIS
    Evaluates DLP (Data Loss Prevention) policies and rules from an OptimizedReport JSON file.
.DESCRIPTION
    - Only considers DLP policies with Mode=Enable as Active for compliance evaluation.
    - Maps each GetDlpCompliancePolicy (parent) to its GetDlpComplianceRule (child) by Guid/Policy.
    - Unpacks AdvancedRule JSON in each rule and recursively extracts all Sensitivetypes > Name.
    - Flags simulation/test policies (Mode=TestWithNotifications, Mode=TestWithoutNotifications, IsSimulationPolicy=true) as informational.
    - Outputs a summary of active DLP policies, their rules, workloads, and detected sensitive types.
.PARAMETER ReportPath
    Path to the OptimizedReport JSON file.
.EXAMPLE
    .\DlpPolicyEvaluator.ps1 -ReportPath .\output\OptimizedReport_*.json
#>

param(
    [Parameter(Mandatory=$true)]
    [string]$ReportPath
)

function Get-SensitiveTypesRecursive {
    param([object]$Node)
    $results = @()
    if ($null -eq $Node) { return $results }
    if ($Node -is [System.Collections.IEnumerable] -and -not ($Node -is [string])) {
        foreach ($item in $Node) {
            $results += Get-SensitiveTypesRecursive -Node $item
        }
    } elseif ($Node -is [hashtable] -or $Node -is [PSCustomObject]) {
        foreach ($key in $Node.PSObject.Properties.Name) {
            if ($key -eq 'Sensitivetypes' -and $Node[$key]) {
                foreach ($stype in $Node[$key]) {
                    if ($stype.Name) { $results += $stype.Name }
                }
            } else {
                $results += Get-SensitiveTypesRecursive -Node $Node[$key]
            }
        }
    }
    return $results
}

if (-not (Test-Path $ReportPath)) {
    Write-Host "File not found: $ReportPath" -ForegroundColor Red
    exit 1
}

$json = Get-Content $ReportPath -Raw | ConvertFrom-Json
$policies = $json.GetDlpCompliancePolicy
$rules = $json.GetDlpComplianceRule

if (-not $policies -or -not $rules) {
    Write-Host "No DLP policies or rules found in report." -ForegroundColor Yellow
    exit 0
}

# Build a lookup for rules by Policy GUID
$rulesByPolicy = @{}
foreach ($rule in $rules) {
    if ($rule.Policy) {
        if (-not $rulesByPolicy.ContainsKey($rule.Policy)) {
            $rulesByPolicy[$rule.Policy] = @()
        }
        $rulesByPolicy[$rule.Policy] += $rule
    }
}

foreach ($policy in $policies) {
    $isSimulation = $false
    if ($policy.Mode -eq 'Enable') {
        $status = 'Active'
    } elseif ($policy.Mode -like 'Test*' -or ($policy.PSObject.Properties.Name -contains 'IsSimulationPolicy' -and $policy.IsSimulationPolicy)) {
        $status = 'Simulation'
        $isSimulation = $true
    } else {
        $status = 'Disabled'
    }
    Write-Host "Policy: $($policy.Name) [$status]" -ForegroundColor Cyan
    Write-Host " Mode: $($policy.Mode) Guid: $($policy.Guid)"
    if ($isSimulation) {
        Write-Host " [INFO] This policy is in simulation/test mode and will not be used for compliance pass/fail." -ForegroundColor Yellow
    }
    if ($status -ne 'Active') { continue }
    if ($rulesByPolicy.ContainsKey($policy.Guid)) {
        foreach ($rule in $rulesByPolicy[$policy.Guid]) {
            Write-Host " Rule: $($rule.Name)"
            Write-Host " Workload: $($rule.Workload)"
            if ($rule.PSObject.Properties.Name -contains 'AdvancedRule' -and $rule.AdvancedRule) {
                try {
                    $adv = $rule.AdvancedRule | ConvertFrom-Json -ErrorAction Stop
                    $stypeNames = Get-SensitiveTypesRecursive -Node $adv | Select-Object -Unique
                    if ($stypeNames) {
                        Write-Host " Sensitive Types: $($stypeNames -join ', ')" -ForegroundColor Green
                    } else {
                        Write-Host " Sensitive Types: None found" -ForegroundColor DarkGray
                    }
                } catch {
                    Write-Host " [ERROR] Failed to parse AdvancedRule JSON." -ForegroundColor Red
                }
            } else {
                Write-Host " No AdvancedRule present." -ForegroundColor DarkGray
            }
        }
    } else {
        Write-Host " No rules found for this policy." -ForegroundColor DarkGray
    }
}