Public/Invoke-LGPolicyCheck.ps1
|
function Invoke-LGPolicyCheck { <# .SYNOPSIS Checks installed software against the policy rules in lg-policy.json. .EXAMPLE Invoke-LGPolicyCheck -PolicyPath .\lg-policy.json .EXAMPLE $sw = Get-LGInstalledSoftware Invoke-LGPolicyCheck -PolicyPath .\lg-policy.json -SoftwareCache $sw #> [CmdletBinding()] param( [string]$PolicyPath = '.\lg-policy.json', [PSCustomObject[]]$SoftwareCache = $null ) $L = Get-LGEffectiveStrings $cfg = Get-LGEffectiveConfig Write-LGHeader $L['policySection'] if (-not (Test-Path $PolicyPath)) { Write-Warning "Policy file not found: $PolicyPath" return @() } try { $policy = Get-Content $PolicyPath -Raw | ConvertFrom-Json } catch { Write-Warning "Could not read policy: $($_.Exception.Message)" return @() } $swRows = if ($SoftwareCache) { $SoftwareCache } else { Get-LGSoftwareRegistryRows -WarnDays $cfg.WarnDaysBeforeExpiry | ForEach-Object { [PSCustomObject]@{ Name=$_.Name; Version=$_.Version; Publisher=$_.Publisher } } } $findings = [System.Collections.Generic.List[PSCustomObject]]::new() foreach ($sw in $swRows) { # Whitelist $whitelisted = $false if ($cfg.Whitelist -and $cfg.Whitelist.Count -gt 0) { foreach ($wl in $cfg.Whitelist) { if ($sw.Name -like "*$wl*") { $whitelisted = $true; break } } } if ($whitelisted) { $findings.Add([PSCustomObject]@{ Module = 'PolicyCheck'; RuleId = 'WL'; Category = 'Whitelist' Name = $sw.Name; Version = $sw.Version; Publisher = $sw.Publisher PolicyStatus = 'ALLOWED'; Status = 'OK'; Detail = $L['whitelist'] Alternative = ''; Reference = ''; Severity = 'LOW' }) continue } # Rule matching $matched = $false foreach ($rule in $policy.rules) { $match = switch ($rule.matchType) { 'contains' { $sw.Name -like "*$($rule.pattern)*" } 'startsWith' { $sw.Name -like "$($rule.pattern)*" } 'exact' { $sw.Name -eq $rule.pattern } 'regex' { $sw.Name -match $rule.pattern } default { $false } } if ($match) { $statusMap = @{ 'PROHIBITED'='EXPIRED'; 'REQUIRES_LICENSE'='WARN'; 'ALLOWED'='OK' } $sevProp = $rule.PSObject.Properties['severity'] $severity = if ($sevProp -and $sevProp.Value) { $sevProp.Value } else { switch ($rule.status) { 'PROHIBITED' { 'HIGH' } 'REQUIRES_LICENSE' { 'MEDIUM' } default { 'LOW' } } } $altProp = $rule.PSObject.Properties['alternative'] $refProp = $rule.PSObject.Properties['referenceUrl'] $findings.Add([PSCustomObject]@{ Module = 'PolicyCheck'; RuleId = $rule.id; Category = $rule.category Name = $sw.Name; Version = $sw.Version; Publisher = $sw.Publisher PolicyStatus = $rule.status; Status = $statusMap[$rule.status]; Detail = $rule.reason Alternative = if ($altProp) { $altProp.Value } else { '' } Reference = if ($refProp) { $refProp.Value } else { '' } Severity = $severity }) $matched = $true; break } } if (-not $matched) { $findings.Add([PSCustomObject]@{ Module = 'PolicyCheck'; RuleId = 'N/A'; Category = 'N/A' Name = $sw.Name; Version = $sw.Version; Publisher = $sw.Publisher PolicyStatus = 'ALLOWED'; Status = 'OK'; Detail = $L['noRule'] Alternative = ''; Reference = ''; Severity = 'LOW' }) } } $proh = @($findings | Where-Object { $_.PolicyStatus -eq 'PROHIBITED' }) $lic = @($findings | Where-Object { $_.PolicyStatus -eq 'REQUIRES_LICENSE' }) $ok = @($findings | Where-Object { $_.PolicyStatus -eq 'ALLOWED' }) foreach ($f in $findings) { $suffix = if ($f.RuleId -notin @('N/A','WL')) { " [$($f.RuleId)]" } else { '' } Write-LGStatus ($f.Name + $suffix) $f.Detail $f.Status if ($f.Status -ne 'OK') { if ($f.Detail) { Write-Host " Reason: $($f.Detail)" -ForegroundColor DarkGray } if ($f.Alternative) { Write-Host " Suggestion: $($f.Alternative)" -ForegroundColor DarkCyan } } } Write-Host ("`n $($findings.Count) matched -- $($proh.Count) $($L['prohibited']) $($lic.Count) $($L['requiresLicense']) $($ok.Count) $($L['allowed'])") -ForegroundColor Cyan $findings } |