Public/Get-ProwlerCheck.ps1

function Get-ProwlerCheck {
    <#
    .SYNOPSIS
        Lists available Prowler checks from the upstream repository.

    .DESCRIPTION
        Queries the upstream Prowler repository for security checks that have been
        added or modified. Returns one object per check with Date, Provider, Service,
        Name, and associated Files.

    .PARAMETER Provider
        Filter to a specific provider (azure, aws, gcp).

    .PARAMETER Service
        Filter to a specific service (e.g., entra, iam, storage).

    .PARAMETER Since
        Only show checks since this date. Defaults to 30 days ago.

    .PARAMETER Limit
        Maximum number of commits to search. Defaults to 50.

    .EXAMPLE
        Get-ProwlerCheck

    .EXAMPLE
        Get-ProwlerCheck -Service entra

    .OUTPUTS
        PSCustomObject with properties: Date, Provider, Service, Name, Files
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter()]
        [ValidateSet('azure', 'aws', 'gcp')]
        [string]$Provider,

        [Parameter()]
        [string]$Service,

        [Parameter()]
        [string]$Since = '30 days ago',

        [Parameter()]
        [int]$Limit = 50
    )

    $ErrorActionPreference = 'Stop'

    # Get supported providers from config
    $supportedProviders = Get-SupportedProvider

    # Verify upstream remote
    Test-GitRemote

    $providersToQuery = if ($Provider) { @($Provider) } else { $supportedProviders }

    Write-Verbose "Searching for check commits..."
    Write-Verbose " Providers: $($providersToQuery -join ', ')"
    Write-Verbose " Since: $Since"
    if ($Service) {
        Write-Verbose " Service: $Service"
    }

    # Fetch from upstream
    $upstreamRemote = $script:Config.prowler.upstreamRemote
    Write-Verbose "Fetching from upstream..."
    git fetch $upstreamRemote --quiet 2>&1 | Out-Null

    # Build file patterns
    $filePatterns = @()
    foreach ($prov in $providersToQuery) {
        $servicePath = if ($Service) { $Service } else { '*' }
        $filePatterns += "prowler/providers/$prov/services/$servicePath/*/*.metadata.json"
        $filePatterns += "prowler/providers/$prov/services/$servicePath/*/*.py"
    }

    # Get commits
    $gitLogArgs = @(
        'log', "$upstreamRemote/master",
        "--since=`"$Since`"", "-n", $Limit,
        '--pretty=format:%H|%s|%an|%ad|%ar',
        '--date=short', '--diff-filter=AM', '--'
    ) + $filePatterns

    $logOutput = & git @gitLogArgs 2>&1

    if ($logOutput) {
        # Parse commits and extract check information
        $logOutput | Where-Object { $_ -and $_ -notmatch '^warning:' } | ForEach-Object {
            $parts = $_ -split '\|', 5
            if ($parts.Count -ge 5) {
                $hash = $parts[0]
                $date = $parts[3]

                # Get files for this commit
                $files = git show --name-only --pretty=format: $hash -- @filePatterns 2>&1 |
                    Where-Object { $_ -and $_ -match '\.metadata\.json$|\.py$' }

                # Extract unique checks from file paths
                $seenChecks = @{}
                foreach ($file in $files) {
                    if ($file -match 'providers/([^/]+)/services/([^/]+)/([^/]+)/') {
                        $fileProvider = $Matches[1]
                        $fileService = $Matches[2]
                        $checkId = $Matches[3]

                        # Create one object per unique check
                        if (-not $seenChecks.ContainsKey($checkId)) {
                            $seenChecks[$checkId] = $true
                            $checkFiles = @($files | Where-Object { $_ -match "/$checkId/" })
                            [PSCustomObject]@{
                                Date     = $date
                                Provider = $fileProvider
                                Service  = $fileService
                                Name     = $checkId
                                Files    = $checkFiles
                            }
                        }
                    }
                }
            }
        }
    }
    else {
        Write-Verbose "No check-related commits found."
    }
}