Public/Sync-ProwlerCheck.ps1
|
function Sync-ProwlerCheck { <# .SYNOPSIS Syncs new Prowler checks from the upstream GitHub repository. .DESCRIPTION Downloads check files from the Prowler GitHub repository that are not yet present locally. No git clone or upstream remote is required. After downloading, new checks are automatically converted to PowerShell format. Use Get-ProwlerCheck to preview available checks first. .PARAMETER Provider Filter to a specific provider (azure, aws, gcp). If not specified, syncs all providers defined in CIEM config. .PARAMETER Service Filter to a specific service (e.g., entra, iam, storage). .PARAMETER Ref Branch, tag, or commit SHA to sync from. Defaults to 'master'. .EXAMPLE Sync-ProwlerCheck # Syncs all check files for supported providers .EXAMPLE Sync-ProwlerCheck -Provider azure -Service entra # Syncs only Entra-related checks .EXAMPLE Sync-ProwlerCheck -Ref 'v4.0.0' # Syncs checks from the v4.0.0 tag #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter()] [ValidateSet('azure', 'aws', 'gcp')] [string]$Provider, [Parameter()] [string]$Service, [Parameter()] [string]$Ref = 'master' ) $ErrorActionPreference = 'Stop' # Resolve local prowler providers path $prowlerProvidersPath = Join-Path $script:ModuleRoot $script:Config.prowler.path $providersToSync = if ($Provider) { @($Provider) } else { (Get-CIEMProvider).Name.ToLower() } Write-Verbose "Syncing Prowler checks from GitHub..." Write-Verbose " Providers: $($providersToSync -join ', ')" if ($Service) { Write-Verbose " Service: $Service" } Write-Verbose " Ref: $Ref" Write-Verbose " Local path: $prowlerProvidersPath" # Get available checks from GitHub $splatParams = @{ Ref = $Ref; ErrorAction = 'Stop' } if ($Provider) { $splatParams.Provider = $Provider } if ($Service) { $splatParams.Service = $Service } $availableChecks = @(Get-ProwlerCheck @splatParams) if ($availableChecks.Count -eq 0) { Write-Verbose "No checks found upstream." return [PSCustomObject]@{ Success = @(); Failed = @(); Skipped = @() } } Write-Verbose "Found $($availableChecks.Count) checks upstream." $success = [System.Collections.Generic.List[string]]::new() $failed = [System.Collections.Generic.List[string]]::new() $skipped = [System.Collections.Generic.List[string]]::new() foreach ($check in $availableChecks) { $localCheckDir = Join-Path $prowlerProvidersPath "$($check.Provider)/services/$($check.Service)/$($check.Name)" if (Test-Path $localCheckDir) { Write-Verbose " Skipping $($check.Name) - already exists locally" $skipped.Add($check.Name) continue } Write-Verbose " Downloading $($check.Name) ($($check.Files.Count) files)..." try { foreach ($file in $check.Files) { # Map GitHub path to local path # GitHub: prowler/providers/{provider}/services/{service}/{check}/{file} # Local: {prowlerProvidersPath}/{provider}/services/{service}/{check}/{file} $relativePath = $file -replace '^prowler/providers/', '' $destination = Join-Path $prowlerProvidersPath $relativePath Save-GitHubRepoFile -Owner 'prowler-cloud' -Repo 'prowler' -Ref $Ref -Path $file -Destination $destination -ErrorAction Stop } Write-Verbose " Downloaded" $success.Add($check.Name) } catch { Write-Verbose " Failed: $_" $failed.Add($check.Name) } } # Convert newly downloaded checks to PowerShell if ($success.Count -gt 0) { Write-Verbose "Converting $($success.Count) new check(s) to PowerShell..." foreach ($checkName in $success) { $check = $availableChecks | Where-Object { $_.Name -eq $checkName } $localCheckDir = Join-Path $prowlerProvidersPath "$($check.Provider)/services/$($check.Service)/$($check.Name)" Write-Verbose " Converting: $checkName" try { Convert-ProwlerCheck -CheckPath $localCheckDir | Out-Null Write-Verbose " Done" } catch { Write-Verbose " Conversion failed: $_" } } } Write-Verbose "Summary: Downloaded=$($success.Count), Skipped=$($skipped.Count), Failed=$($failed.Count)" [PSCustomObject]@{ Success = @($success) Failed = @($failed) Skipped = @($skipped) } } |