modules/Devolutions.CIEM.Checks/Public/Get-CIEMCheck.ps1
|
function Get-CIEMCheck { <# .SYNOPSIS Lists available CIEM security checks. .DESCRIPTION Reads check metadata exclusively from the SQLite database (checks table). Returns PSCustomObjects (not class instances) to ensure compatibility with PSU runspaces where PowerShell class types may not be available. .PARAMETER Provider Filter checks by cloud provider (Azure, AWS). .PARAMETER Service Filter checks by service name (e.g., Entra, IAM, KeyVault, Storage, iam, s3). .PARAMETER Severity Filter checks by severity level (critical, high, medium, low). .PARAMETER CheckId Filter to one or more checks by ID. Accepts a single string or an array. .OUTPUTS [PSCustomObject[]] Array of check objects with properties: Id, Provider, Service, Title, Description, Risk, Severity, Remediation, RelatedUrl, CheckScript, DependsOn, DataNeeds, Permissions. .EXAMPLE Get-CIEMCheck # Returns all checks across all providers .EXAMPLE Get-CIEMCheck -Provider AWS # Returns all AWS checks .EXAMPLE Get-CIEMCheck -Service Entra -Severity high # Returns high-severity Entra checks .EXAMPLE Get-CIEMCheck -CheckId 'entra_security_defaults_enabled' # Returns specific check details #> [CmdletBinding()] param( [Parameter()] [string]$Provider, [Parameter()] [string]$Service, [Parameter()] [ValidateSet('critical', 'high', 'medium', 'low')] [string]$Severity, [Parameter()] [string[]]$CheckId ) $ErrorActionPreference = 'Stop' # Build parameterized query with filters $conditions = @() $params = @{} if ($PSBoundParameters.ContainsKey('Provider')) { $conditions += "provider = @provider" $params.provider = $Provider } if ($Service) { $conditions += "service = @service" $params.service = $Service } if ($Severity) { $conditions += "severity = @severity" $params.severity = $Severity } if ($CheckId) { if ($CheckId.Count -eq 1) { $conditions += "id = @id" $params.id = $CheckId[0] } else { $placeholders = @() for ($i = 0; $i -lt $CheckId.Count; $i++) { $placeholders += "@id$i" $params["id$i"] = $CheckId[$i] } $conditions += "id IN ($($placeholders -join ', '))" } } $query = "SELECT * FROM checks" if ($conditions.Count -gt 0) { $query += " WHERE " + ($conditions -join ' AND ') } $rows = @(Invoke-CIEMQuery -Query $query -Parameters $params) # Convert rows to the expected PSCustomObject shape $checks = @(foreach ($row in $rows) { # Parse permissions JSON $permissionsObj = & { $p = @{ Graph = @(); ARM = @(); KeyVaultDataPlane = @(); IAM = @() } if ($row.permissions) { try { $raw = $row.permissions | ConvertFrom-Json foreach ($prop in $raw.PSObject.Properties) { switch ($prop.Name.ToLower()) { 'graph' { $p.Graph = @($prop.Value) } 'arm' { $p.ARM = @($prop.Value) } 'keyvaultdataplane' { $p.KeyVaultDataPlane = @($prop.Value) } 'iam' { $p.IAM = @($prop.Value) } } } } catch { Write-Verbose "Failed to parse permissions JSON for check $($row.id): $_" } } [PSCustomObject]$p } # Parse depends_on JSON $dependsOnArr = @() if ($row.depends_on) { try { $dependsOnArr = @($row.depends_on | ConvertFrom-Json) } catch { Write-Verbose "Failed to parse depends_on JSON for check $($row.id): $_" } } $dataNeedsArr = $null if ($row.data_needs) { try { $dataNeedsArr = @($row.data_needs | ConvertFrom-Json) } catch { Write-Verbose "Failed to parse data_needs JSON for check $($row.id): $_" } } [PSCustomObject]@{ Id = $row.id Provider = $row.provider Service = $row.service Title = $row.title Description = $row.description Risk = $row.risk Severity = $row.severity Remediation = [PSCustomObject]@{ Text = $row.remediation_text Url = $row.remediation_url } RelatedUrl = $row.related_url CheckScript = $row.check_script DependsOn = $dependsOnArr DataNeeds = $dataNeedsArr Disabled = [bool]$row.disabled Permissions = $permissionsObj } }) $checks } |