mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
chore(skills): improve compliance coverage, validation & docs (#12062)
This commit is contained in:
@@ -62,6 +62,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
| Action | Skill |
|
||||
|--------|-------|
|
||||
| Add changelog entry for a PR or feature | `prowler-changelog` |
|
||||
| Adding ConfigRequirements guardrails to compliance requirements | `prowler-compliance` |
|
||||
| Adding DRF pagination or permissions | `django-drf` |
|
||||
| Adding a compliance output formatter (per-provider class + table dispatcher) | `prowler-compliance` |
|
||||
| Adding indexes or constraints to database tables | `django-migration-psql` |
|
||||
@@ -84,6 +85,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
| Creating ViewSets, serializers, or filters in api/ | `django-drf` |
|
||||
| Creating Zod schemas | `zod-4` |
|
||||
| Creating a git commit | `prowler-commit` |
|
||||
| Creating a universal (multi-provider) compliance framework | `prowler-compliance` |
|
||||
| Creating new checks | `prowler-sdk-check` |
|
||||
| Creating new skills | `skill-creator` |
|
||||
| Creating or reviewing Django migrations | `django-migration-psql` |
|
||||
|
||||
+923
-783
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
# Audit Reference: Requirement Text → Prowler Checks
|
||||
|
||||
Built from a real audit of 172 CCC ARs × 3 providers (April 2026). Use it to map
|
||||
CCC-style / NIST-style / ISO-style requirement text to the checks that actually
|
||||
verify them. Always re-validate every check id against the current inventory
|
||||
(`assets/build_inventory.py` + `assets/query_checks.py`) before using a row —
|
||||
checks get renamed and added over time.
|
||||
|
||||
**Entries containing `*` are glob patterns, NOT literal check ids** (e.g.
|
||||
`iam_*_no_administrative_privileges`, `cloudwatch_log_metric_filter_*`,
|
||||
`*_minimum_tls_version_12`). Copied verbatim into a compliance JSON they map
|
||||
nothing — expand each pattern to the concrete check ids via
|
||||
`python skills/prowler-compliance/assets/query_checks.py <provider> <keywords>`
|
||||
before writing any mapping.
|
||||
|
||||
| Requirement text | AWS checks | Azure checks | GCP checks |
|
||||
|---|---|---|---|
|
||||
| **TLS in transit enforced** | `cloudfront_distributions_https_enabled`, `s3_bucket_secure_transport_policy`, `elbv2_ssl_listeners`, `elbv2_insecure_ssl_ciphers`, `elb_ssl_listeners`, `elb_insecure_ssl_ciphers`, `opensearch_service_domains_https_communications_enforced`, `rds_instance_transport_encrypted`, `redshift_cluster_in_transit_encryption_enabled`, `elasticache_redis_cluster_in_transit_encryption_enabled`, `dynamodb_accelerator_cluster_in_transit_encryption_enabled`, `dms_endpoint_ssl_enabled`, `kafka_cluster_in_transit_encryption_enabled`, `transfer_server_in_transit_encryption_enabled`, `glue_database_connections_ssl_enabled`, `sns_subscription_not_using_http_endpoints` | `storage_secure_transfer_required_is_enabled`, `storage_ensure_minimum_tls_version_12`, `postgresql_flexible_server_enforce_ssl_enabled`, `mysql_flexible_server_ssl_connection_enabled`, `mysql_flexible_server_minimum_tls_version_12`, `sqlserver_recommended_minimal_tls_version`, `app_minimum_tls_version_12`, `app_ensure_http_is_redirected_to_https`, `app_ftp_deployment_disabled` | `cloudsql_instance_ssl_connections` (almost only option) |
|
||||
| **TLS 1.3 specifically** | Partial: `cloudfront_distributions_using_deprecated_ssl_protocols`, `elb*_insecure_ssl_ciphers`, `*_minimum_tls_version_12` | Partial: `*_minimum_tls_version_12` checks | None — accept as MANUAL |
|
||||
| **SSH / port 22 hardening** | `ec2_instance_port_ssh_exposed_to_internet`, `ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22`, `ec2_networkacl_allow_ingress_tcp_port_22` | `network_ssh_internet_access_restricted`, `vm_linux_enforce_ssh_authentication` | `compute_firewall_ssh_access_from_the_internet_allowed`, `compute_instance_block_project_wide_ssh_keys_disabled`, `compute_project_os_login_enabled`, `compute_project_os_login_2fa_enabled` |
|
||||
| **mTLS (mutual TLS)** | `kafka_cluster_mutual_tls_authentication_enabled`, `apigateway_restapi_client_certificate_enabled` | `app_client_certificates_on` | None — MANUAL |
|
||||
| **Data at rest encrypted** | `s3_bucket_default_encryption`, `s3_bucket_kms_encryption`, `ec2_ebs_default_encryption`, `ec2_ebs_volume_encryption`, `rds_instance_storage_encrypted`, `rds_cluster_storage_encrypted`, `rds_snapshots_encrypted`, `dynamodb_tables_kms_cmk_encryption_enabled`, `redshift_cluster_encrypted_at_rest`, `neptune_cluster_storage_encrypted`, `documentdb_cluster_storage_encrypted`, `opensearch_service_domains_encryption_at_rest_enabled`, `kinesis_stream_encrypted_at_rest`, `firehose_stream_encrypted_at_rest`, `sns_topics_kms_encryption_at_rest_enabled`, `sqs_queues_server_side_encryption_enabled`, `efs_encryption_at_rest_enabled`, `athena_workgroup_encryption`, `glue_data_catalogs_metadata_encryption_enabled`, `backup_vaults_encrypted`, `backup_recovery_point_encrypted`, `cloudtrail_kms_encryption_enabled`, `cloudwatch_log_group_kms_encryption_enabled`, `eks_cluster_kms_cmk_encryption_in_secrets_enabled`, `sagemaker_notebook_instance_encryption_enabled`, `apigateway_restapi_cache_encrypted`, `kafka_cluster_encryption_at_rest_uses_cmk`, `dynamodb_accelerator_cluster_encryption_enabled`, `storagegateway_fileshare_encryption_enabled` | `storage_infrastructure_encryption_is_enabled`, `storage_ensure_encryption_with_customer_managed_keys`, `vm_ensure_attached_disks_encrypted_with_cmk`, `vm_ensure_unattached_disks_encrypted_with_cmk`, `sqlserver_tde_encryption_enabled`, `sqlserver_tde_encrypted_with_cmk`, `databricks_workspace_cmk_encryption_enabled`, `monitor_storage_account_with_activity_logs_cmk_encrypted` | `compute_instance_encryption_with_csek_enabled`, `dataproc_encrypted_with_cmks_disabled`, `bigquery_dataset_cmk_encryption`, `bigquery_table_cmk_encryption` |
|
||||
| **CMEK required (customer-managed keys)** | `kms_cmk_are_used` | `storage_ensure_encryption_with_customer_managed_keys`, `vm_ensure_attached_disks_encrypted_with_cmk`, `vm_ensure_unattached_disks_encrypted_with_cmk`, `sqlserver_tde_encrypted_with_cmk`, `databricks_workspace_cmk_encryption_enabled` | `bigquery_dataset_cmk_encryption`, `bigquery_table_cmk_encryption`, `dataproc_encrypted_with_cmks_disabled`, `compute_instance_encryption_with_csek_enabled` |
|
||||
| **Key rotation enabled** | `kms_cmk_rotation_enabled` | `keyvault_key_rotation_enabled`, `storage_key_rotation_90_days` | `kms_key_rotation_enabled` |
|
||||
| **MFA for UI access** | `iam_root_mfa_enabled`, `iam_root_hardware_mfa_enabled`, `iam_user_mfa_enabled_console_access`, `iam_user_hardware_mfa_enabled`, `iam_administrator_access_with_mfa`, `cognito_user_pool_mfa_enabled` | `entra_privileged_user_has_mfa`, `entra_non_privileged_user_has_mfa`, `entra_user_with_vm_access_has_mfa`, `entra_security_defaults_enabled` | `compute_project_os_login_2fa_enabled` |
|
||||
| **API access / credentials** | `iam_no_root_access_key`, `iam_user_no_setup_initial_access_key`, `apigateway_restapi_authorizers_enabled`, `apigateway_restapi_public_with_authorizer`, `apigatewayv2_api_authorizers_enabled` | `entra_conditional_access_policy_require_mfa_for_management_api`, `app_function_access_keys_configured`, `app_function_identity_is_configured` | `apikeys_api_restrictions_configured`, `apikeys_key_exists`, `apikeys_key_rotated_in_90_days` |
|
||||
| **Log all admin/config changes** | `cloudtrail_multi_region_enabled`, `cloudtrail_multi_region_enabled_logging_management_events`, `cloudtrail_cloudwatch_logging_enabled`, `cloudtrail_log_file_validation_enabled`, `cloudwatch_log_metric_filter_*`, `cloudwatch_changes_to_*_alarm_configured`, `config_recorder_all_regions_enabled` | `monitor_diagnostic_settings_exists`, `monitor_diagnostic_setting_with_appropriate_categories`, `monitor_alert_*` | `iam_audit_logs_enabled`, `logging_log_metric_filter_and_alert_for_*`, `logging_sink_created` |
|
||||
| **Log integrity (digital signatures)** | `cloudtrail_log_file_validation_enabled` (exact) | None | None |
|
||||
| **Public access denied** | `s3_bucket_public_access`, `s3_bucket_public_list_acl`, `s3_bucket_public_write_acl`, `s3_account_level_public_access_blocks`, `apigateway_restapi_public`, `awslambda_function_url_public`, `awslambda_function_not_publicly_accessible`, `rds_instance_no_public_access`, `rds_snapshots_public_access`, `ec2_securitygroup_allow_ingress_from_internet_to_all_ports`, `sns_topics_not_publicly_accessible`, `sqs_queues_not_publicly_accessible` | `storage_blob_public_access_level_is_disabled`, `storage_ensure_private_endpoints_in_storage_accounts`, `containerregistry_not_publicly_accessible`, `keyvault_private_endpoints`, `app_function_not_publicly_accessible`, `aks_clusters_public_access_disabled`, `network_http_internet_access_restricted` | `cloudstorage_bucket_public_access`, `compute_instance_public_ip`, `cloudsql_instance_public_ip`, `compute_firewall_*_access_from_the_internet_allowed` |
|
||||
| **IAM least privilege** | `iam_*_no_administrative_privileges`, `iam_policy_allows_privilege_escalation`, `iam_inline_policy_allows_privilege_escalation`, `iam_role_administratoraccess_policy`, `iam_group_administrator_access_policy`, `iam_user_administrator_access_policy`, `iam_policy_attached_only_to_group_or_roles`, `iam_role_cross_service_confused_deputy_prevention` | `iam_role_user_access_admin_restricted`, `iam_subscription_roles_owner_custom_not_created`, `iam_custom_role_has_permissions_to_administer_resource_locks` | `iam_sa_no_administrative_privileges`, `iam_no_service_roles_at_project_level`, `iam_role_kms_enforce_separation_of_duties`, `iam_role_sa_enforce_separation_of_duties` |
|
||||
| **Password policy** | `iam_password_policy_minimum_length_14`, `iam_password_policy_uppercase`, `iam_password_policy_lowercase`, `iam_password_policy_symbol`, `iam_password_policy_number`, `iam_password_policy_expires_passwords_within_90_days_or_less`, `iam_password_policy_reuse_24` | None | None |
|
||||
| **Credential rotation / unused** | `iam_rotate_access_key_90_days`, `iam_user_accesskey_unused`, `iam_user_console_access_unused` | None | `iam_sa_user_managed_key_rotate_90_days`, `iam_sa_user_managed_key_unused`, `iam_service_account_unused` |
|
||||
| **VPC / flow logs** | `vpc_flow_logs_enabled` | `network_flow_log_captured_sent`, `network_watcher_enabled`, `network_flow_log_more_than_90_days` | `compute_subnet_flow_logs_enabled` |
|
||||
| **Backup / DR / Multi-AZ** | `backup_vaults_exist`, `backup_plans_exist`, `backup_reportplans_exist`, `rds_instance_backup_enabled`, `rds_*_protected_by_backup_plan`, `rds_cluster_multi_az`, `neptune_cluster_backup_enabled`, `documentdb_cluster_backup_enabled`, `efs_have_backup_enabled`, `s3_bucket_cross_region_replication`, `dynamodb_table_protected_by_backup_plan` | `vm_backup_enabled`, `vm_sufficient_daily_backup_retention_period`, `storage_geo_redundant_enabled` | `cloudsql_instance_automated_backups`, `cloudstorage_bucket_log_retention_policy_lock`, `cloudstorage_bucket_sufficient_retention_period` |
|
||||
| **Access analysis / discovery** | `accessanalyzer_enabled`, `accessanalyzer_enabled_without_findings` | None specific | `iam_account_access_approval_enabled`, `iam_cloud_asset_inventory_enabled` |
|
||||
| **Object lock / retention** | `s3_bucket_object_lock`, `s3_bucket_object_versioning`, `s3_bucket_lifecycle_enabled`, `cloudtrail_bucket_requires_mfa_delete`, `s3_bucket_no_mfa_delete` | `storage_ensure_soft_delete_is_enabled`, `storage_blob_versioning_is_enabled`, `storage_ensure_file_shares_soft_delete_is_enabled` | `cloudstorage_bucket_log_retention_policy_lock`, `cloudstorage_bucket_soft_delete_enabled`, `cloudstorage_bucket_versioning_enabled`, `cloudstorage_bucket_sufficient_retention_period` |
|
||||
| **Uniform bucket-level access** | `s3_bucket_acl_prohibited` | `storage_account_key_access_disabled`, `storage_default_to_entra_authorization_enabled` | `cloudstorage_bucket_uniform_bucket_level_access` |
|
||||
| **Container vulnerability scanning** | `ecr_registry_scan_images_on_push_enabled`, `ecr_repositories_scan_vulnerabilities_in_latest_image` | `defender_container_images_scan_enabled`, `defender_container_images_resolved_vulnerabilities` | `artifacts_container_analysis_enabled`, `gcr_container_scanning_enabled` |
|
||||
| **WAF / rate limiting** | `wafv2_webacl_with_rules`, `waf_*_webacl_with_rules`, `wafv2_webacl_logging_enabled`, `waf_global_webacl_logging_enabled` | None | None |
|
||||
| **Deployment region restriction** | `organizations_scp_check_deny_regions` | None | None |
|
||||
| **Secrets automatic rotation** | `secretsmanager_automatic_rotation_enabled`, `secretsmanager_secret_rotated_periodically` | `keyvault_rbac_secret_expiration_set`, `keyvault_non_rbac_secret_expiration_set` | None |
|
||||
| **Certificate management** | `acm_certificates_expiration_check`, `acm_certificates_with_secure_key_algorithms`, `acm_certificates_transparency_logs_enabled` | `keyvault_key_expiration_set_in_non_rbac`, `keyvault_rbac_key_expiration_set`, `keyvault_non_rbac_secret_expiration_set` | None |
|
||||
| **GenAI guardrails / input/output filtering** | `bedrock_guardrail_prompt_attack_filter_enabled`, `bedrock_guardrail_sensitive_information_filter_enabled`, `bedrock_agent_guardrail_enabled`, `bedrock_model_invocation_logging_enabled`, `bedrock_api_key_no_administrative_privileges`, `bedrock_api_key_no_long_term_credentials` | None | None |
|
||||
| **ML dev environment security** | `sagemaker_notebook_instance_root_access_disabled`, `sagemaker_notebook_instance_without_direct_internet_access_configured`, `sagemaker_notebook_instance_vpc_settings_configured`, `sagemaker_models_vpc_settings_configured`, `sagemaker_training_jobs_vpc_settings_configured`, `sagemaker_training_jobs_network_isolation_enabled`, `sagemaker_training_jobs_volume_and_output_encryption_enabled` | None | None |
|
||||
| **Threat detection / anomalous behavior** | `cloudtrail_threat_detection_enumeration`, `cloudtrail_threat_detection_privilege_escalation`, `cloudtrail_threat_detection_llm_jacking`, `guardduty_is_enabled`, `guardduty_no_high_severity_findings` | None | None |
|
||||
| **Serverless private access** | `awslambda_function_inside_vpc`, `awslambda_function_not_publicly_accessible`, `awslambda_function_url_public` | `app_function_not_publicly_accessible` | None |
|
||||
|
||||
## What Prowler Does NOT Cover (accept MANUAL honestly)
|
||||
|
||||
Don't pad mappings for these — mark the requirement's checks empty and move on:
|
||||
|
||||
- **TLS 1.3 version specifically** — Prowler verifies TLS is enforced, not always the exact version
|
||||
- **IANA port-protocol consistency** — no check for "protocol running on its assigned port"
|
||||
- **mTLS on most Azure/GCP services** — limited to App Service client certs on Azure, nothing on GCP
|
||||
- **Rate limiting** on monitoring endpoints, load balancers, serverless invocations, vector ingestion
|
||||
- **Session cookie expiry** (LB stickiness)
|
||||
- **HTTP header scrubbing** (Server, X-Powered-By)
|
||||
- **Certificate transparency verification for imports**
|
||||
- **Model version pinning, red teaming, AI quality review**
|
||||
- **Vector embedding validation, dimensional constraints, ANN vs exact search**
|
||||
- **Secret region replication** (cross-region residency)
|
||||
- **Lifecycle cleanup policies on container registries**
|
||||
- **Row-level / column-level security in data warehouses**
|
||||
- **Deployment region restriction on Azure/GCP** (AWS has `organizations_scp_check_deny_regions`, others don't)
|
||||
- **Cross-tenant alert silencing permissions**
|
||||
- **Field-level masking in logs**
|
||||
- **Managed view enforcement for database access**
|
||||
- **Automatic MFA delete on all S3 buckets** (only CloudTrail bucket variant exists for some frameworks — AWS has the generic `s3_bucket_no_mfa_delete` though)
|
||||
|
||||
## Provider coverage asymmetry
|
||||
|
||||
AWS has dense coverage (in-transit encryption, IAM, database encryption, backup,
|
||||
GenAI). Azure and GCP are thinner, especially for in-transit encryption, mTLS,
|
||||
and ML/AI. Accept the asymmetry in mappings — don't force GCP parity where
|
||||
Prowler genuinely can't verify. Newer providers (alibabacloud, oraclecloud,
|
||||
googleworkspace, okta, cloudflare, linode...) have far smaller inventories:
|
||||
always rebuild the inventory with `assets/build_inventory.py` before assuming
|
||||
a mapping exists.
|
||||
@@ -1,137 +1,154 @@
|
||||
# Compliance Framework Documentation
|
||||
# Compliance Framework Quick Reference
|
||||
|
||||
## Code References
|
||||
|
||||
Key files for understanding and modifying compliance frameworks:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `prowler/lib/check/compliance_models.py` | Pydantic models defining attribute structures for each framework type |
|
||||
| `prowler/lib/check/compliance.py` | Core compliance processing logic |
|
||||
| `prowler/lib/check/utils.py` | Utility functions including `list_compliance_modules()` |
|
||||
| `prowler/lib/outputs/compliance/` | Framework-specific output generators |
|
||||
| `prowler/compliance/{provider}/` | JSON compliance framework definitions |
|
||||
| `prowler/lib/check/compliance_models.py` | Legacy + universal Pydantic (v1) model trees, config-constraint model, loaders, legacy→universal adapter |
|
||||
| `prowler/lib/check/compliance.py` | `update_checks_metadata_with_compliance()` (only) |
|
||||
| `prowler/lib/check/compliance_config_eval.py` | Shared `ConfigRequirements` guardrail evaluation (SDK outputs + API) |
|
||||
| `prowler/lib/outputs/compliance/compliance_check.py` | `get_check_compliance()` — per-finding `{Framework}-{Version}` → requirement ids |
|
||||
| `prowler/lib/check/utils.py` | `list_compliance_modules()` |
|
||||
| `prowler/lib/outputs/compliance/` | Output formatters (legacy per-framework + `universal/`) |
|
||||
| `prowler/compliance/*.json` | Universal multi-provider framework definitions |
|
||||
| `prowler/compliance/{provider}/` | Legacy per-provider framework definitions |
|
||||
|
||||
## Attribute Model Classes
|
||||
## Attribute Model Classes (legacy schema)
|
||||
|
||||
Each framework type has a specific Pydantic model in `compliance_models.py`:
|
||||
Registered in the `Compliance_Requirement.Attributes` Union, in this order
|
||||
(order is load-bearing; Generic must stay last):
|
||||
|
||||
| Framework | Model Class |
|
||||
| Framework family | Model Class |
|
||||
|-----------|-------------|
|
||||
| ASD Essential Eight | `ASDEssentialEight_Requirement_Attribute` |
|
||||
| CIS | `CIS_Requirement_Attribute` |
|
||||
| ISO 27001 | `ISO27001_2013_Requirement_Attribute` |
|
||||
| ENS | `ENS_Requirement_Attribute` |
|
||||
| MITRE ATT&CK | `Mitre_Requirement` (uses different structure) |
|
||||
| ISO 27001 | `ISO27001_2013_Requirement_Attribute` |
|
||||
| AWS Well-Architected | `AWS_Well_Architected_Requirement_Attribute` |
|
||||
| KISA ISMS-P | `KISA_ISMSP_Requirement_Attribute` |
|
||||
| Prowler ThreatScore | `Prowler_ThreatScore_Requirement_Attribute` |
|
||||
| CCC | `CCC_Requirement_Attribute` |
|
||||
| C5 Germany | `C5Germany_Requirement_Attribute` |
|
||||
| Generic/Fallback | `Generic_Compliance_Requirement_Attribute` |
|
||||
| CSA CCM (legacy shape) | `CSA_CCM_Requirement_Attribute` |
|
||||
| DISA STIG (Okta IDaaS) | `STIG_Requirement_Attribute` |
|
||||
| Generic/Fallback (NIST, PCI, GDPR, HIPAA, SOC2, FedRAMP, ...) | `Generic_Compliance_Requirement_Attribute` |
|
||||
|
||||
## How Compliance Frameworks are Loaded
|
||||
MITRE ATT&CK uses the separate `Mitre_Requirement` model with per-provider
|
||||
`Mitre_Requirement_Attribute_{AWS,Azure,GCP}` attribute classes.
|
||||
|
||||
1. `Compliance.get_bulk(provider)` is called at startup
|
||||
2. Scans `prowler/compliance/{provider}/` for `.json` files
|
||||
3. Each file is parsed using `load_compliance_framework()`
|
||||
4. Pydantic validates against `Compliance` model
|
||||
5. Framework is stored in dictionary with filename (without `.json`) as key
|
||||
`Compliance_Requirement_ConfigConstraint` models each `ConfigRequirements` /
|
||||
`config_requirements` entry (`Check`, `ConfigKey`, `Operator`, `Value`,
|
||||
optional `Provider`) with load-time operator/value type validation.
|
||||
|
||||
## Universal Schema Models
|
||||
|
||||
| Model | Purpose |
|
||||
|-------|---------|
|
||||
| `ComplianceFramework` | Top-level container (`framework`, `name`, `version`, `requirements`, `attributes_metadata`, `outputs`); validates attributes against metadata at load |
|
||||
| `UniversalComplianceRequirement` | Flat `attributes: dict`, `checks: dict[provider, list]`, `config_requirements`, MITRE extras |
|
||||
| `AttributeMetadata` | Per-attribute schema descriptor (key/label/type/enum/required/`enum_display`/`enum_order`/`output_formats`) |
|
||||
| `OutputsConfig` → `TableConfig` | CLI table rendering (`group_by`, `split_by`, `scoring`, `labels`) — consumed by `universal_table.py` |
|
||||
| `OutputsConfig` → `PDFConfig` (+ `ChartConfig`, `ScoringFormula`, `I18nLabels`, ...) | Declarative PDF config — modeled but **not yet consumed** by the API PDF pipeline (it uses its own `FRAMEWORK_REGISTRY`) |
|
||||
|
||||
## How Frameworks Are Loaded
|
||||
|
||||
Two entry points — they see different files:
|
||||
|
||||
1. **Legacy**: `Compliance.get_bulk(provider)` scans only
|
||||
`prowler/compliance/{provider}/` (exact provider-segment match) plus
|
||||
external JSONs from the `prowler.compliance` entry-point group. Invalid
|
||||
built-in file → `logger.critical` + `sys.exit(1)`
|
||||
(`load_compliance_framework`, `fatal=True`).
|
||||
2. **Universal**: `get_bulk_compliance_frameworks_universal(provider)` scans
|
||||
the top-level `prowler/compliance/` **and** every provider subdirectory,
|
||||
plus the `prowler.compliance.universal` entry-point group (built-ins win
|
||||
collisions). Legacy files are adapted via `adapt_legacy_to_universal()`
|
||||
(flattens `Attributes[0]` into a dict, wraps `Checks` as
|
||||
`{provider: [...]}`, infers `attributes_metadata` from the matched Pydantic
|
||||
class). Invalid file → logged and **skipped**
|
||||
(`load_compliance_framework_universal` returns `None`).
|
||||
|
||||
The framework key in both bulk dicts is the JSON basename without `.json` —
|
||||
that's also the `--compliance` CLI key.
|
||||
|
||||
## How Checks Map to Compliance
|
||||
|
||||
1. After loading, `update_checks_metadata_with_compliance()` is called
|
||||
2. For each check, it finds all compliance requirements that reference it
|
||||
3. Compliance info is attached to `CheckMetadata.Compliance` list
|
||||
4. During output, `get_check_compliance()` retrieves mappings per finding
|
||||
1. `update_checks_metadata_with_compliance()` attaches, per check, every
|
||||
framework requirement that references it (`CheckMetadata.Compliance`).
|
||||
2. During output, `get_check_compliance()`
|
||||
(`prowler/lib/outputs/compliance/compliance_check.py`) returns the
|
||||
per-finding dict `{"{Framework}-{Version}": [requirement_ids]}` — the
|
||||
`-{Version}` suffix only exists when `Version` is non-empty.
|
||||
3. `ConfigRequirements` guardrails are evaluated by
|
||||
`evaluate_config_constraints()` (`compliance_config_eval.py`); a violated
|
||||
constraint forces FAIL and prepends
|
||||
`Configuration not valid for this requirement.` to `status_extended` in
|
||||
every output format.
|
||||
|
||||
## File Naming Convention
|
||||
## File Naming Conventions
|
||||
|
||||
```text
|
||||
{framework}_{version}_{provider}.json
|
||||
prowler/compliance/{framework}_{version}.json # universal
|
||||
prowler/compliance/{provider}/{framework}_{version}_{provider}.json # legacy
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `cis_5.0_aws.json`
|
||||
- `iso27001_2022_azure.json`
|
||||
- `mitre_attack_gcp.json`
|
||||
- `ens_rd2022_aws.json`
|
||||
- `nist_800_53_revision_5_aws.json`
|
||||
Examples: `dora_2022_2554.json`, `cis_controls_8.1.json`, `cis_7.0_aws.json`,
|
||||
`iso27001_2022_azure.json`, `okta_idaas_stig_v1r2_okta.json`,
|
||||
`cisa_scuba_0.6_googleworkspace.json`, `ccc_aws.json` (unversioned only when
|
||||
the framework has no versioning). For legacy files the version substring in
|
||||
the filename must equal `Version`.
|
||||
|
||||
## Validation
|
||||
## Validation Summary
|
||||
|
||||
Prowler validates compliance JSON at startup. Invalid files cause:
|
||||
- `ValidationError` logged with details
|
||||
- Application exit with error code
|
||||
- **Load time (universal)**: `attributes_metadata` root validator — required
|
||||
keys, unknown-key drift guard, enums, int/float/bool types. Omit the
|
||||
metadata and nothing is validated.
|
||||
- **Load time (legacy)**: Pydantic attribute-class matching; a shape matching
|
||||
no specific class silently falls through to Generic.
|
||||
- **Never validated at load**: check-id existence. Cross-check manually
|
||||
(see SKILL.md → Validation).
|
||||
- **Test suite**: `tests/lib/check/universal_compliance_models_test.py::test_loads_as_universal`
|
||||
is parametrized over every shipped JSON (top-level + per-provider).
|
||||
- **CI**: `.github/workflows/pr-check-compliance-mapping.yml` flags new checks
|
||||
not mapped in any framework (`needs-compliance-review` label; opt out with
|
||||
`no-compliance-check`).
|
||||
- **Pre-commit**: `check-json` + `pretty-format-json` only (syntax/format, no
|
||||
semantics).
|
||||
- **Manual**: `skills/prowler-compliance-review/assets/validate_compliance.py`
|
||||
(legacy schema only).
|
||||
|
||||
Common validation errors:
|
||||
- Missing required fields (`Id`, `Description`, `Checks`, `Attributes`)
|
||||
- Invalid enum values (e.g., `Profile` must be "Level 1" or "Level 2" for CIS)
|
||||
- Type mismatches (e.g., `Checks` must be array of strings)
|
||||
## Repo Tooling (`util/compliance/`)
|
||||
|
||||
## Adding a New Framework
|
||||
|
||||
1. Create JSON file in `prowler/compliance/{provider}/`
|
||||
2. Use appropriate attribute model (see table above)
|
||||
3. Map existing checks to requirements via `Checks` array
|
||||
4. Use empty `Checks: []` for manual-only requirements
|
||||
5. Test with `prowler {provider} --list-compliance` to verify loading
|
||||
6. Run `prowler {provider} --compliance {framework_name}` to test execution
|
||||
|
||||
## Templates
|
||||
|
||||
See `assets/` directory for example templates:
|
||||
- `cis_framework.json` - CIS Benchmark template
|
||||
- `iso27001_framework.json` - ISO 27001 template
|
||||
- `ens_framework.json` - ENS (Spain) template
|
||||
- `mitre_attack_framework.json` - MITRE ATT&CK template
|
||||
- `prowler_threatscore_framework.json` - Prowler ThreatScore template
|
||||
- `generic_framework.json` - Generic/custom framework template
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `util/compliance/generate_json_from_csv/*.py` | CSV→JSON generators (CIS 1.5, CIS 2.0 GCP, CIS 1.0 GitHub, CIS 4.0 M365, ENS, ThreatScore) |
|
||||
| `util/compliance/ccc/from_yaml_to_json.py` | FINOS CCC YAML→JSON converter |
|
||||
| `util/compliance/compliance_mapper/` | Compliance mapper (see its README) |
|
||||
| `util/compliance/threatscore/get_prowler_threatscore_from_generic_output.py` | Derive ThreatScore from generic output |
|
||||
|
||||
## Prowler ThreatScore Details
|
||||
|
||||
Prowler ThreatScore is a custom security scoring framework that calculates an overall security posture score based on:
|
||||
Custom Prowler scoring framework. Pillars / ID prefixes: `1.x.x` IAM, `2.x.x`
|
||||
Attack Surface, `3.x.x` Logging and Monitoring, `4.x.x` Encryption.
|
||||
|
||||
### Four Pillars
|
||||
1. **IAM (Identity and Access Management)**
|
||||
- SubSections: Authentication, Authorization, Credentials Management
|
||||
|
||||
2. **Attack Surface**
|
||||
- SubSections: Network Exposure, Storage Exposure, Service Exposure
|
||||
|
||||
3. **Logging and Monitoring**
|
||||
- SubSections: Audit Logging, Threat Detection, Alerting
|
||||
|
||||
4. **Encryption**
|
||||
- SubSections: Data at Rest, Data in Transit
|
||||
|
||||
### Scoring Algorithm
|
||||
The ThreatScore uses `LevelOfRisk` and `Weight` to calculate severity:
|
||||
|
||||
| LevelOfRisk | Weight | Example Controls |
|
||||
|-------------|--------|------------------|
|
||||
| 5 (Critical) | 1000 | Root MFA, No root access keys, Public S3 buckets |
|
||||
| 4 (High) | 100 | User MFA, Public EC2, GuardDuty enabled |
|
||||
| 3 (Medium) | 10 | Password policies, EBS encryption, CloudTrail |
|
||||
| 2 (Low) | 1-10 | Best practice recommendations |
|
||||
| 1 (Info) | 1 | Informational controls |
|
||||
|
||||
### ID Numbering Convention
|
||||
- `1.x.x` - IAM controls
|
||||
- `2.x.x` - Attack Surface controls
|
||||
- `3.x.x` - Logging and Monitoring controls
|
||||
- `4.x.x` - Encryption controls
|
||||
Scoring: `LevelOfRisk` 1–5 (5=critical) × `Weight` (values in the shipped
|
||||
catalogs: 1000 critical / 100 high / 8–10 standard / 1 low). Available for
|
||||
aws, azure, gcp, kubernetes, m365, alibabacloud.
|
||||
|
||||
## External Resources
|
||||
|
||||
### Official Framework Documentation
|
||||
- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks)
|
||||
- [ISO 27001:2022](https://www.iso.org/standard/27001)
|
||||
- [CIS Critical Security Controls](https://www.cisecurity.org/controls)
|
||||
- [ISO 27001](https://www.iso.org/standard/27001)
|
||||
- [NIST 800-53](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final)
|
||||
- [NIST CSF](https://www.nist.gov/cyberframework)
|
||||
- [PCI DSS](https://www.pcisecuritystandards.org/)
|
||||
- [MITRE ATT&CK](https://attack.mitre.org/)
|
||||
- [ENS (Spain)](https://www.ccn-cert.cni.es/es/ens.html)
|
||||
|
||||
### Prowler Documentation
|
||||
- [Prowler Docs - Compliance](https://docs.prowler.com/projects/prowler-open-source/en/latest/)
|
||||
- [Prowler GitHub](https://github.com/prowler-cloud/prowler)
|
||||
- [FINOS CCC](https://github.com/finos/common-cloud-controls)
|
||||
- [CSA CCM](https://cloudsecurityalliance.org/research/cloud-controls-matrix)
|
||||
- [DORA (EU 2022/2554)](https://eur-lex.europa.eu/eli/reg/2022/2554/oj)
|
||||
- [ASD Essential Eight](https://www.cyber.gov.au/resources-business-and-government/essential-cybersecurity/essential-eight)
|
||||
- [CISA SCuBA](https://www.cisa.gov/resources-tools/services/secure-cloud-business-applications-scuba-project)
|
||||
- [DISA STIGs](https://public.cyber.mil/stigs/)
|
||||
- [Prowler Docs — Compliance developer guide](https://docs.prowler.com/developer-guide/security-compliance-framework)
|
||||
|
||||
Reference in New Issue
Block a user