Skip to main content

prowler-compliance

Creates, syncs, audits and manages Prowler compliance frameworks end-to-end. Covers the two supported JSON schemas (universal multi-provider and legacy per-provider), the SDK model tree (legacy attribute classes, universal ComplianceFramework, ConfigRequirements guardrails), output formatters (legacy per-framework + universal data-driven), API/UI consumption, upstream sync workflows, and cloud-auditor check-mapping reviews. Trigger: When working with compliance frameworks (CIS, CIS Controls, NIST, PCI-DSS, SOC2, GDPR, ISO27001, ENS, MITRE ATT&CK, CCC, C5, CSA CCM, DORA, KISA ISMS-P, ASD Essential Eight, DISA STIG, CISA SCuBA, SecNumCloud, FedRAMP, HIPAA, NIS2, Prowler ThreatScore), creating a universal multi-provider framework, adding ConfigRequirements guardrails, syncing with upstream catalogs, auditing check-to-requirement mappings, adding output formatters, or fixing compliance JSON bugs (duplicate IDs, empty Version, wrong Section, stale check refs).

Ir a la instalación

Datos de origen

Repositorio
prowler-cloud/prowler
Última actividad en el origen
21 de julio de 2026 a las 08:24
Idioma detectado de SKILL.md
inglés
Estrellas
14.842
Forks
2391

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
17 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
prowler-compliance
description
Creates, syncs, audits and manages Prowler compliance frameworks end-to-end. Covers the two supported JSON schemas (universal multi-provider and legacy per-provider), the SDK model tree (legacy attribute classes, universal ComplianceFramework, ConfigRequirements guardrails), output formatters (legacy per-framework + universal data-driven), API/UI consumption, upstream sync workflows, and cloud-auditor check-mapping reviews. Trigger: When working with compliance frameworks (CIS, CIS Controls, NIST, PCI-DSS, SOC2, GDPR, ISO27001, ENS, MITRE ATT&CK, CCC, C5, CSA CCM, DORA, KISA ISMS-P, ASD Essential Eight, DISA STIG, CISA SCuBA, SecNumCloud, FedRAMP, HIPAA, NIS2, Prowler ThreatScore), creating a universal multi-provider framework, adding ConfigRequirements guardrails, syncing with upstream catalogs, auditing check-to-requirement mappings, adding output formatters, or fixing compliance JSON bugs (duplicate IDs, empty Version, wrong Section, stale check refs).
license
Apache-2.0
metadata
{"author":"prowler-cloud","version":"2.0","scope":["root","sdk"],"auto_invoke":["Creating/updating compliance frameworks","Creating a universal (multi-provider) compliance framework","Mapping checks to compliance controls","Adding ConfigRequirements guardrails to compliance requirements","Syncing compliance framework with upstream catalog","Auditing check-to-requirement mappings as a cloud auditor","Adding a compliance output formatter (per-provider class + table dispatcher)","Fixing compliance JSON bugs (duplicate IDs, empty Section, stale refs)"]}
allowed-tools
Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
## When to Use Use this skill when: - Creating a new compliance framework for any provider — **decide universal vs legacy first** (see below) - **Syncing an existing framework with an upstream source of truth** (CIS, FINOS CCC, CSA CCM, NIST, ENS, etc.) - Adding requirements to existing frameworks, or extending a universal framework to a new provider - Mapping checks to compliance controls - **Adding `ConfigRequirements` guardrails** so configurable checks can't silently satisfy a requirement with a loosened config - **Auditing existing check mappings as a cloud auditor** ("are these mappings correct?", "which checks apply?", "review the mappings") - **Adding a new legacy output formatter** (table dispatcher + per-provider classes + CSV models) - **Fixing JSON bugs**: duplicate IDs, empty Version, wrong Section, stale check refs, inconsistent FamilyName, padded tangential check mappings - Investigating why a finding/check isn't showing under the expected compliance framework in the UI - Understanding compliance framework structures and attributes The authoritative contributor doc is `docs/developer-guide/security-compliance-framework.mdx` — keep this skill and that doc consistent when either changes. For **reviewing** a compliance PR, use the sister skill [prowler-compliance-review](../prowler-compliance-review/SKILL.md) instead. ## Universal vs Legacy: The First Decision Prowler supports **two JSON schemas**. Choosing wrong means unnecessary Python code, so decide this before anything else. At load time both converge: legacy files are adapted into the universal `ComplianceFramework` model (`adapt_legacy_to_universal()`), so the difference is about **authoring cost and capabilities**, not about what the rest of Prowler sees. ### Side-by-side comparison | | Universal (recommended for new frameworks) | Legacy provider-specific | |---|---|---| | File location | `prowler/compliance/<framework>.json` (top level) | `prowler/compliance/<provider>/<framework>_<version>_<provider>.json` | | Providers | Any number, one file (`checks` dict keyed by provider) | Exactly one provider per file (one file per provider to multi-cover) | | Key style | lowercase (`framework`, `requirements`, `checks`) | Capitalized (`Framework`, `Requirements`, `Checks`) | | Attribute schema | Declared **in the JSON itself** via `attributes_metadata`, validated at load | Pydantic class per framework family in `compliance_models.py` (code change for new shapes) | | Attributes per requirement | One flat dict (`attributes: {...}`) | List of objects (`Attributes: [{...}]`) — only `Attributes[0]` is used downstream | | Table/CSV/OCSF output | Data-driven from `outputs.table_config` — **zero Python changes** | Formatter package + registrations in `compliance.py`, `__main__.py`, `export.py` | | Guardrails field | `config_requirements` (+ mandatory `Provider` per constraint) | `ConfigRequirements` (`Provider` omitted) | | Loader behavior on error | Lenient: logs + skips file (`load_compliance_framework_universal`) | Fail-fast: `sys.exit(1)` (`load_compliance_framework`) | | Loaded by | Only `get_bulk_compliance_frameworks_universal()` | Both loaders (`Compliance.get_bulk()` + universal, via adapter) | | Shipped examples | `cis_controls_8.1.json`, `csa_ccm_4.0.json`, `dora_2022_2554.json` | Everything else (~105 files across 11 providers) | ### When to use which **Use universal when** (any of these): - The framework is **new to Prowler** — no existing attribute class, no existing formatter. This is the default: zero Python changes needed. - The framework spans (or will span) **more than one provider** — DORA, CSA CCM, CIS Controls. One file covers all providers; extending to a new provider is a one-line `checks` edit. - The attribute shape is **unique to this framework** — declare it in `attributes_metadata` instead of adding a Pydantic class to the Union. **Use legacy only when extending an existing legacy family**: - A new **version** of a shipped legacy framework (CIS 8.0 for AWS → new `cis_8.0_aws.json`, same `CIS_Requirement_Attribute`, same `cis/` formatter). - An existing legacy framework for a **new provider** (ENS for m365 → new `ens_rd2022_m365.json` + `ens_m365.py` transformer). - Consistency with the family matters more than the universal benefits — a lone `cis_8.0_aws` in universal format while 20+ CIS files stay legacy would fragment the family. **Never**: start a brand-new single-provider framework as legacy "because it's only AWS today". Universal handles single-provider fine (the `checks` dict just has one key) and you skip 3 output files + 3 registrations. ### The same requirement in both schemas Universal (`prowler/compliance/my_framework_1.0.json`): ```json { "framework": "My-Framework", "name": "My Framework 1.0", "version": "1.0", "description": "...", "attributes_metadata": [ {"key": "Section", "type": "str", "required": true}, {"key": "Service", "type": "str"} ], "outputs": {"table_config": {"group_by": "Section"}}, "requirements": [ { "id": "MF-1.1", "name": "Root MFA", "description": "Root account must have MFA enabled.", "attributes": {"Section": "IAM", "Service": "iam"}, "checks": { "aws": ["iam_root_mfa_enabled"], "azure": [] } } ] } ``` Legacy (`prowler/compliance/aws/my_framework_1.0_aws.json` — plus a second file per extra provider, plus formatter + registrations): ```json { "Framework": "My-Framework", "Name": "My Framework 1.0 for AWS", "Version": "1.0", "Provider": "AWS", "Description": "...", "Requirements": [ { "Id": "MF-1.1", "Name": "Root MFA", "Description": "Root account must have MFA enabled.", "Attributes": [ {"ItemId": "MF-1.1", "Section": "IAM", "Service": "iam"} ], "Checks": ["iam_root_mfa_enabled"] } ] } ``` Same control, but the universal file already covers Azure, validates its own attribute schema, and renders table/CSV/OCSF with no code. Field-by-field references for each schema follow below. ## Architecture (Mental Model) Prowler compliance is a four-layer system. Bugs usually happen where one layer doesn't match another, so know all four before touching anything. ### Layer 1: SDK / Core Models — `prowler/lib/check/` All in **Pydantic v1** (`from pydantic.v1 import ...`). Three model groups live in `compliance_models.py`: **Legacy tree** — `Compliance` → `Compliance_Requirement` / `Mitre_Requirement`: - One `*_Requirement_Attribute` class per framework family. Registered today (Union order matters): `ASDEssentialEight`, `CIS`, `ENS`, `ISO27001_2013`, `AWS_Well_Architected`, `KISA_ISMSP`, `Prowler_ThreatScore`, `CCC`, `C5Germany`, `CSA_CCM`, `STIG` (Okta IDaaS), and `Generic_Compliance_Requirement_Attribute` as fallback. - **Generic MUST stay LAST** in `Compliance_Requirement.Attributes: list[Union[...]]` — Pydantic v1 tries union members in order; Generic first would swallow every framework-specific attribute. NIST 800-53/CSF, PCI DSS, GDPR, HIPAA, SOC2, FedRAMP, SecNumCloud etc. intentionally use Generic. - A `root_validator` rejects empty `Framework`, `Provider` or `Name`. - MITRE uses the separate `Mitre_Requirement` model (`Tactics`, `SubTechniques`, `Platforms`, `TechniqueURL` at requirement top level, per-provider `Mitre_Requirement_Attribute_{AWS,Azure,GCP}`). **Universal tree** — `ComplianceFramework` → `UniversalComplianceRequirement`: - Flat `attributes: dict` per requirement, schema declared in `attributes_metadata` (key, label, type, enum, required, `enum_display`, `enum_order`, `output_formats`). A `root_validator` rejects missing required keys, unknown keys (drift guard), enum violations, and int/float/bool type mismatches. If `attributes_metadata` is omitted, **no validation runs**. - `checks: dict[provider, list[check_id]]` — the provider list of the framework is **derived** from these keys (`get_providers()` / `supports_provider()`); the top-level `provider` field is only a fallback. - `outputs.table_config` (group_by, split_by, scoring, labels) drives the CLI table; `outputs.pdf_config` exists in the model but **is not consumed by the API PDF pipeline yet** (see Layer 4). **Guardrails** — `Compliance_Requirement_ConfigConstraint`: - Fields `Check`, `ConfigKey`, `Operator` (`lte|gte|eq|in|subset|superset`), `Value`, optional `Provider` (required in universal multi-provider files). - A `root_validator` rejects Value/Operator type mismatches at load time. - Evaluation is centralized in `prowler/lib/check/compliance_config_eval.py` (`evaluate_config_constraints`, `apply_config_status`, `get_effective_status`, `CONFIG_NOT_VALID_PREFIX = "Configuration not valid for this requirement."`), shared by CSV/OCSF/table outputs **and** the API backend. A violated constraint forces the requirement to FAIL and prepends the reason to `status_extended`. Constraints whose `ConfigKey` is absent from `audit_config` are skipped (defaults assumed compliant). **Loaders**: - `Compliance.get_bulk(provider)` — legacy: scans only `prowler/compliance/{provider}/` (+ external JSONs via the `prowler.compliance` entry-point group). Does NOT see top-level universal files. - `get_bulk_compliance_frameworks_universal(provider)` — scans **both** the top-level `prowler/compliance/` and every provider subdirectory, adapting legacy files via `adapt_legacy_to_universal()` (flattens `Attributes[0]` to a dict, wraps `Checks` as `{provider: [...]}`, infers `attributes_metadata`). Also loads external universal frameworks via the `prowler.compliance.universal` entry-point group (built-ins win collisions). - `get_check_compliance(finding, provider_type, bulk_checks_metadata)` lives in **`prowler/lib/outputs/compliance/compliance_check.py`** (not in `lib/check/compliance.py`). It builds the per-finding dict keyed `f"{Framework}-{Version}"` **only when Version is non-empty** — an empty Version silently produces the key `"{Framework}"` and breaks downstream filters and tests. - `prowler/lib/check/compliance.py` now contains only `update_checks_metadata_with_compliance()`. ### Layer 2: JSON Catalogs — `prowler/compliance/` See "Compliance Catalog Coverage" below. ### Layer 3: Output Formatters — `prowler/lib/outputs/compliance/` **Universal path** (no Python needed per framework): - `universal/universal_table.py` — `get_universal_table()`, renders the CLI table from `outputs.table_config` + `attributes_metadata`. - `universal/universal_output.py` — `UniversalComplianceOutput`, builds the CSV Pydantic model **dynamically** from `attributes_metadata`. - `universal/ocsf_compliance.py` — `OCSFComplianceOutput`; OCSF output is **always generated** for universal frameworks regardless of `--output-formats`. - Orchestrated by `process_universal_compliance_frameworks()` in `compliance.py`, which runs **before** any legacy dispatch and removes the processed frameworks from the set. **Legacy path** — per-framework directory, usually: ```text {framework}/ ├── __init__.py ├── {framework}.py # get_{framework}_table() summary-table function ├── {framework}_{provider}.py # One ComplianceOutput subclass per provider └── models.py # One Pydantic CSV row model per provider ``` Directories today: `asd_essential_eight`, `aws_well_architected`, `c5`, `ccc`, `cis`, `cisa_scuba`, `ens`, `generic`, `iso27001`, `kisa_ismsp`, `mitre_attack`, `okta_idaas_stig`, `prowler_threatscore`, `universal`. Known deviations (don't "fix" them without a reason): `iso27001/` has no table file (falls to the generic table), `aws_well_architected/` has no per-provider files, `cisa_scuba/` only ships googleworkspace. - CSV writers emit `;`-delimited files with UPPERCASE headers (`ComplianceOutput.batch_write_data_to_file`). Field names in `models.py` are **public API** — renaming breaks downstream consumers. - **Circular import rule**: the table file (`{framework}.py`) must not import `Finding` directly or transitively (`compliance.compliance` → table module → `ComplianceOutput` → `Finding` → `get_check_compliance` → cycle). Keep table files bare (`colorama`, `tabulate`, `prowler.config.config`); when a module genuinely needs both, use `if TYPE_CHECKING:` or function-local imports (see `universal_output.py` / `process_universal_compliance_frameworks`). - Legacy table functions have no docstrings; the universal ones do. Match the style of the file family you're touching. - Dispatcher `display_compliance_table()` in `compliance.py` order: universal (`table_config`) first → `cis_` → `ens_` → `mitre_attack` → `kisa` → `prowler_threatscore_` → `c5_` → `ccc_` → `asd_essential_eight` (substring) → `okta_idaas_stig` → else provider hook (`provider.display_compliance_table()`, may raise `NotImplementedError`) → `get_generic_compliance_table()`. iso27001, aws_well_architected and cisa_scuba ride the fallback on purpose.
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub