From 3860cd3dceab27381c0e56595e367e39ddc2ef7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Mon, 14 Sep 2026 16:35:05 +0200 Subject: [PATCH] feat(compliance): FedRAMP 20x Class C FRR + AWS checks (#12808) --- README.md | 10 +- contrib/k8s/helm/prowler-api/values.yaml | 8 + docs/developer-guide/configurable-checks.mdx | 2 + .../cli/tutorials/configuration_file.mdx | 10 + permissions/prowler-additions-policy.json | 1 + .../cloudformation/prowler-scan-role.yml | 2 + .../aws-inspector2-fips-checks.added.md | 1 + .../fedramp-20x-frr-class-c-2026.added.md | 1 + .../fedramp_20x_frr_class_c_2026.json | 2970 +++++++++++++++++ prowler/config/config.yaml | 8 + prowler/config/schema/aws.py | 14 + .../__init__.py | 0 ...v2_listener_fips_tls_enabled.metadata.json | 43 + .../elbv2_listener_fips_tls_enabled.py | 35 + .../__init__.py | 0 ...findings_kev_within_due_date.metadata.json | 42 + ...or2_active_findings_kev_within_due_date.py | 66 + .../__init__.py | 0 ...wn_exploited_vulnerabilities.metadata.json | 43 + ...ings_no_known_exploited_vulnerabilities.py | 57 + .../__init__.py | 0 ...tive_findings_within_max_age.metadata.json | 43 + ...spector2_active_findings_within_max_age.py | 51 + .../__init__.py | 0 ...r2_coverage_recently_scanned.metadata.json | 43 + .../inspector2_coverage_recently_scanned.py | 57 + .../__init__.py | 0 ..._coverage_scan_status_active.metadata.json | 42 + .../inspector2_coverage_scan_status_active.py | 46 + .../services/inspector2/inspector2_service.py | 201 ++ .../aws/services/inspector2/lib/__init__.py | 0 .../inspector2/lib/vulnerabilities.py | 8 + .../__init__.py | 0 ...fips_security_policy_enabled.metadata.json | 42 + ...fer_server_fips_security_policy_enabled.py | 38 + tests/config/config_test.py | 2 + tests/config/fixtures/config.yaml | 8 + .../elbv2_listener_fips_tls_enabled_test.py | 156 + ...ctive_findings_kev_within_due_date_test.py | 136 + ...no_known_exploited_vulnerabilities_test.py | 149 + ...or2_active_findings_within_max_age_test.py | 140 + ...spector2_coverage_recently_scanned_test.py | 170 + ...ector2_coverage_scan_status_active_test.py | 132 + .../inspector2/inspector2_service_test.py | 220 +- ...erver_fips_security_policy_enabled_test.py | 111 + 45 files changed, 5100 insertions(+), 8 deletions(-) create mode 100644 prowler/changelog.d/aws-inspector2-fips-checks.added.md create mode 100644 prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md create mode 100644 prowler/compliance/fedramp_20x_frr_class_c_2026.json create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py create mode 100644 prowler/providers/aws/services/inspector2/lib/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/lib/vulnerabilities.py create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py create mode 100644 tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py create mode 100644 tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py diff --git a/README.md b/README.md index ad69260cb0..2851101f05 100644 --- a/README.md +++ b/README.md @@ -126,12 +126,12 @@ Every AWS provider scan will enqueue an Attack Paths ingestion job automatically | Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/user-guide/compliance/tutorials/compliance) | [Categories](https://docs.prowler.com/user-guide/cli/tutorials/misc#categories) | Support | Interface | |---|---|---|---|---|---|---| -| AWS | 639 | 86 | 47 | 19 | Official | UI, API, CLI | -| Azure | 191 | 22 | 21 | 16 | Official | UI, API, CLI | -| GCP | 109 | 20 | 19 | 12 | Official | UI, API, CLI | -| Kubernetes | 92 | 7 | 8 | 11 | Official | UI, API, CLI | +| AWS | 662 | 86 | 50 | 19 | Official | UI, API, CLI | +| Azure | 191 | 22 | 25 | 16 | Official | UI, API, CLI | +| GCP | 110 | 20 | 22 | 12 | Official | UI, API, CLI | +| Kubernetes | 92 | 7 | 11 | 11 | Official | UI, API, CLI | | GitHub | 24 | 3 | 2 | 5 | Official | UI, API, CLI | -| M365 | 143 | 10 | 6 | 10 | Official | UI, API, CLI | +| M365 | 144 | 10 | 9 | 10 | Official | UI, API, CLI | | OCI | 52 | 14 | 5 | 10 | Official | UI, API, CLI | | Alibaba Cloud | 63 | 9 | 6 | 9 | Official | UI, API, CLI | | Cloudflare | 29 | 3 | 2 | 5 | Official | UI, API, CLI | diff --git a/contrib/k8s/helm/prowler-api/values.yaml b/contrib/k8s/helm/prowler-api/values.yaml index a6074c7852..5332f9d2eb 100644 --- a/contrib/k8s/helm/prowler-api/values.yaml +++ b/contrib/k8s/helm/prowler-api/values.yaml @@ -212,6 +212,14 @@ mainConfig: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/docs/developer-guide/configurable-checks.mdx b/docs/developer-guide/configurable-checks.mdx index 04a31a8cde..c44f82c5aa 100644 --- a/docs/developer-guide/configurable-checks.mdx +++ b/docs/developer-guide/configurable-checks.mdx @@ -154,6 +154,8 @@ Only fields with a numeric range, a fixed value set, or a length cap are listed. | `max_days_secret_unused` | `7..365` days | | | `max_days_secret_unrotated` | `1..180` days | NIST IA-5: rotate quarterly; CIS ≤90 | | `min_kinesis_stream_retention_hours` | `24..8760` h | 1 day .. 1 year | +| `inspector2_max_days_since_last_scan` | `1..90` days | | +| `inspector2_active_finding_max_age_days` | `1..365` days | Default `192` matches the FedRAMP 20x rule that marks vulnerabilities still open after 192 days as accepted | | `shodan_api_key` | ≤512 chars | | ### Azure diff --git a/docs/user-guide/cli/tutorials/configuration_file.mdx b/docs/user-guide/cli/tutorials/configuration_file.mdx index ac21f5bc6c..a1c14e6626 100644 --- a/docs/user-guide/cli/tutorials/configuration_file.mdx +++ b/docs/user-guide/cli/tutorials/configuration_file.mdx @@ -91,6 +91,8 @@ The following list includes all the AWS checks with configurable variables that | `iam_user_access_not_stale_to_sagemaker` | `max_unused_sagemaker_access_days` | Integer | `90` | | `iam_user_accesskey_unused` | `max_unused_access_keys_days` | Integer | `45` | | `iam_user_console_access_unused` | `max_console_access_days` | Integer | `45` | +| `inspector2_active_findings_within_max_age` | `inspector2_active_finding_max_age_days` | Integer | `192` | +| `inspector2_coverage_recently_scanned` | `inspector2_max_days_since_last_scan` | Integer | `3` | | `kinesis_stream_data_retention_period` | `min_kinesis_stream_retention_hours` | Integer | `168` | | `neptune_cluster_backup_enabled` | `minimum_backup_retention_period` | Integer | `7` | | `opensearch_service_domains_not_publicly_accessible` | `trusted_ips` | List of Strings | `[]` | @@ -490,6 +492,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/permissions/prowler-additions-policy.json b/permissions/prowler-additions-policy.json index 25ea46b09d..be17979d2e 100644 --- a/permissions/prowler-additions-policy.json +++ b/permissions/prowler-additions-policy.json @@ -38,6 +38,7 @@ "glue:GetSecurityConfiguration*", "glue:SearchTables", "glue:GetMLTransforms", + "inspector2:BatchGetFindingDetails", "lambda:GetFunction*", "lambda:GetLayerVersion", "logs:FilterLogEvents", diff --git a/permissions/templates/cloudformation/prowler-scan-role.yml b/permissions/templates/cloudformation/prowler-scan-role.yml index d04c8f25d6..d31dea9846 100644 --- a/permissions/templates/cloudformation/prowler-scan-role.yml +++ b/permissions/templates/cloudformation/prowler-scan-role.yml @@ -210,6 +210,7 @@ Resources: - "glue:GetSecurityConfiguration*" - "glue:SearchTables" - "glue:GetMLTransforms" + - "inspector2:BatchGetFindingDetails" - "lambda:GetFunction*" - "logs:FilterLogEvents" - "lightsail:GetRelationalDatabases" @@ -479,6 +480,7 @@ Resources: - "glue:GetSecurityConfiguration*" - "glue:SearchTables" - "glue:GetMLTransforms" + - "inspector2:BatchGetFindingDetails" - "lambda:GetFunction*" - "logs:FilterLogEvents" - "lightsail:GetRelationalDatabases" diff --git a/prowler/changelog.d/aws-inspector2-fips-checks.added.md b/prowler/changelog.d/aws-inspector2-fips-checks.added.md new file mode 100644 index 0000000000..40c36f8062 --- /dev/null +++ b/prowler/changelog.d/aws-inspector2-fips-checks.added.md @@ -0,0 +1 @@ +`inspector2_coverage_scan_status_active`, `inspector2_coverage_recently_scanned`, `inspector2_active_findings_no_known_exploited_vulnerabilities`, `inspector2_active_findings_kev_within_due_date`, `inspector2_active_findings_within_max_age`, `elbv2_listener_fips_tls_enabled` and `transfer_server_fips_security_policy_enabled` checks for AWS provider, covering FedRAMP 20x Class C vulnerability detection, CISA KEV remediation and FIPS cryptography rules; the KEV checks require `inspector2:BatchGetFindingDetails`, now in the Prowler additions policy diff --git a/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md b/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md new file mode 100644 index 0000000000..147ad052f3 --- /dev/null +++ b/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md @@ -0,0 +1 @@ +`FedRAMP-20x-FRR-Class-C` universal compliance framework (`fedramp_20x_frr_class_c_2026`) with the 158 provider rules of the FedRAMP 20x Class C ruleset from the FedRAMP Consolidated Rules 2026 for AWS, Azure, GCP, Kubernetes and M365 diff --git a/prowler/compliance/fedramp_20x_frr_class_c_2026.json b/prowler/compliance/fedramp_20x_frr_class_c_2026.json new file mode 100644 index 0000000000..f4db7f37bd --- /dev/null +++ b/prowler/compliance/fedramp_20x_frr_class_c_2026.json @@ -0,0 +1,2970 @@ +{ + "framework": "FedRAMP-20x-FRR-Class-C", + "name": "FedRAMP 20x Class C Rules (FRR) 2026", + "version": "2026.09.13.02", + "description": "FedRAMP Rules (FRR) that cloud service providers must follow for a FedRAMP 20x Class C Certification, from the FedRAMP Consolidated Rules for 2026 (release 2026.09.13.02, https://github.com/FedRAMP/rules). Covers the 158 provider rules of the 15 rulesets on the 20x Class C reference page; rules that only bind FedRAMP, agencies, assessors or advisors are excluded, and class-varying rules use their Class C statement. Most rules are program and process obligations that need manual evidence. The Key Security Indicators of the same ruleset are in the fedramp_20x_ksi_2026 framework.", + "icon": "fedramp", + "attributes_metadata": [ + { + "key": "Ruleset", + "label": "Ruleset", + "type": "str", + "required": true, + "enum": [ + "AFC: Addressing FedRAMP Communication", + "CCM: Collaborative Continuous Monitoring", + "CDS: Certification Data Sharing", + "CMU: Cryptographic Module Use", + "CPO: Certification Package Overview", + "FRC: FedRAMP Certification", + "IEC: Incident Evaluation and Communication", + "IVV: Independent Verification and Validation", + "MAS: Minimum Assessment Scope", + "MKT: Marketplace Listing", + "SCG: Secure Configuration Guide", + "SCN: Significant Change Notification", + "SDR: Security Decision Record", + "VDR: Vulnerability Detection and Response", + "VER: Vulnerability Evaluation and Reporting" + ] + }, + { + "key": "Subset", + "label": "Subset", + "type": "str", + "required": true + }, + { + "key": "Force", + "label": "Force", + "type": "str", + "required": true, + "enum": [ + "MUST", + "MUST NOT", + "SHOULD", + "SHOULD NOT", + "MAY" + ] + } + ], + "outputs": { + "table_config": { + "group_by": "Ruleset" + }, + "pdf_config": { + "language": "en", + "primary_color": "#1B3A5C", + "secondary_color": "#2E6DA4", + "bg_color": "#F0F4FA", + "group_by_field": "Ruleset", + "sections": [ + "AFC: Addressing FedRAMP Communication", + "CCM: Collaborative Continuous Monitoring", + "CDS: Certification Data Sharing", + "CMU: Cryptographic Module Use", + "CPO: Certification Package Overview", + "FRC: FedRAMP Certification", + "IEC: Incident Evaluation and Communication", + "IVV: Independent Verification and Validation", + "MAS: Minimum Assessment Scope", + "MKT: Marketplace Listing", + "SCG: Secure Configuration Guide", + "SCN: Significant Change Notification", + "SDR: Security Decision Record", + "VDR: Vulnerability Detection and Response", + "VER: Vulnerability Evaluation and Reporting" + ], + "section_short_names": { + "AFC: Addressing FedRAMP Communication": "AFC", + "CCM: Collaborative Continuous Monitoring": "CCM", + "CDS: Certification Data Sharing": "CDS", + "CMU: Cryptographic Module Use": "CMU", + "CPO: Certification Package Overview": "CPO", + "FRC: FedRAMP Certification": "FRC", + "IEC: Incident Evaluation and Communication": "IEC", + "IVV: Independent Verification and Validation": "IVV", + "MAS: Minimum Assessment Scope": "MAS", + "MKT: Marketplace Listing": "MKT", + "SCG: Secure Configuration Guide": "SCG", + "SCN: Significant Change Notification": "SCN", + "SDR: Security Decision Record": "SDR", + "VDR: Vulnerability Detection and Response": "VDR", + "VER: Vulnerability Evaluation and Reporting": "VER" + }, + "charts": [ + { + "id": "ruleset_compliance", + "type": "horizontal_bar", + "group_by": "Ruleset", + "title": "Compliance Score by FRR Ruleset", + "y_label": "Ruleset", + "x_label": "Compliance %", + "value_source": "compliance_percent", + "color_mode": "by_value" + } + ], + "filter": { + "only_failed": true, + "include_manual": false + } + } + }, + "requirements": [ + { + "id": "AFC-CSO-INB", + "name": "Maintain a FedRAMP Security Inbox", + "description": "Providers MUST establish and maintain an email address to receive messages from FedRAMP; this inbox is a FedRAMP Security Inbox (FSI).", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-NOC", + "name": "Notification of Changes", + "description": "Providers MUST immediately notify FedRAMP of any changes to the email address for their FedRAMP Security Inbox.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-TFG", + "name": "Trust @fedramp.gov and @gsa.gov", + "description": "Providers MUST treat any email originating from an @fedramp.gov or @gsa.gov email address as if it was sent from FedRAMP by default; if such a message is confirmed to originate from someone other than FedRAMP then the FedRAMP Security Inbox rules no longer apply.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-RCV", + "name": "Receive Email Without Disruption", + "description": "Providers MUST receive and react to email messages from FedRAMP without disruption and without requiring additional actions from FedRAMP.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-CRA", + "name": "Complete Required Actions", + "description": "Providers MUST complete the required actions in Emergency or Emergency Test designated messages sent by FedRAMP within the timeframe included in the message.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-EMR", + "name": "Emergency Message Routing", + "description": "Providers MUST route Emergency designated messages sent by FedRAMP to a senior security official for their awareness.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-IMA", + "name": "Important Message Actions", + "description": "Providers SHOULD complete the required actions in Important designated messages sent by FedRAMP within the timeframe specified in the message.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-ACK", + "name": "Acknowledge Receipt", + "description": "Providers SHOULD promptly and automatically acknowledge the receipt of messages received from FedRAMP in their FedRAMP Security Inbox.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-AVL", + "name": "Report Availability", + "description": "Providers MUST supply an Ongoing Certification Report to all necessary parties every 3 months, covering the entire period since the previous summary, in a consistent format that is human readable; this report MUST include high-level summaries of at least the following information (if applicable): Changes to FedRAMP Certification Data; Planned changes to FedRAMP Certification Data during at least the next 3 months; Accepted vulnerabilities; Transformative changes; Updated recommendations or best practices for security, configuration, usage, or similar aspects of the cloud service offering; A list of all agencies that are directly using the product; FedRAMP Reportable Incidents or an attestation that no such incidents occurred; Lessons learned and changes planned or made as a result of FedRAMP Reportable Incidents (if such occurred)", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-NRD", + "name": "Next Report Date", + "description": "Providers MUST supply the target date for their next Ongoing Certification Report with other public FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-FBM", + "name": "Feedback Mechanism", + "description": "Providers MUST supply an asynchronous mechanism for all necessary parties to provide feedback or ask questions about each Ongoing Certification Report.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-AFS", + "name": "Anonymized Feedback Summary", + "description": "Providers MUST supply an anonymized and desensitized summary of the feedback, questions, and answers about each Ongoing Certification Report as an addendum to the Ongoing Certification Report OR in the next Ongoing Certification Report.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-LSI", + "name": "Limit Sensitive Information", + "description": "Providers MUST NOT irresponsibly disclose sensitive information in an Ongoing Certification Report that would likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-SOR", + "name": "Spread Out Reports", + "description": "Providers SHOULD establish a regular 3 month cycle for Ongoing Certification Reports that is spread out from the beginning, middle, or end of each quarter.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-RPS", + "name": "Responsible Public Certification Report Sharing", + "description": "Providers MAY responsibly supply some or all of the information an Ongoing Certification Report to the public or other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-MTG", + "name": "Quarterly Review Meeting", + "description": "Providers with Class C Certifications MUST host a synchronous Quarterly Review every 3 months, open to all necessary parties, to review aspects of the most recent Ongoing Certification Reports that the provider determines are of the most relevance to agencies.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-REG", + "name": "Meeting Registration Info", + "description": "Providers MUST supply either a registration link or a downloadable calendar file with meeting information for Quarterly Reviews to all necessary parties.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-NRD", + "name": "Next Review Date", + "description": "Providers MUST publicly supply the target date for their next Quarterly Review with other public FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-NID", + "name": "No Irresponsible Disclosure", + "description": "Providers MUST NOT irresponsibly disclose sensitive information in a Quarterly Review that would likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SAR", + "name": "Schedule Around Reports", + "description": "Providers SHOULD regularly schedule Quarterly Reviews to occur at least 3 business days after releasing an Ongoing Certification Report AND within 10 business days of such release.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-ACT", + "name": "Additional Content", + "description": "Providers SHOULD supply additional information in Quarterly Reviews that the provider determines is of interest, use, or otherwise relevant to agencies.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-RTR", + "name": "Record/Transcribe Reviews", + "description": "Providers SHOULD record or transcribe Quarterly Reviews and supply them to all necessary parties.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-RTP", + "name": "Restrict Third Parties", + "description": "Providers SHOULD NOT invite third parties to attend Quarterly Reviews intended for agencies unless they have specific relevance.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SRR", + "name": "Share Recordings Responsibly", + "description": "Providers MAY responsibly supply recordings or transcriptions of Quarterly Reviews to the public or other parties ONLY if the provider removes all agency information (comments, questions, names, etc.) AND determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SCR", + "name": "Share Content Responsibly", + "description": "Providers MAY responsibly supply content prepared for a Quarterly Review to the public or other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-PUB", + "name": "Public Information", + "description": "Providers MUST publicly share up-to-date information about the cloud service offering in both human-readable and JSON formats, including at least the following information that is available and applicable: FedRAMP ID; Service Model; Deployment Model; Business Category; UEI Number; Sales Contact Information; Security Contact Information; Product Website Link; Link to Product Logo; Overall Service Description; Detailed list of specific services and their security categories (see CDS-CSO-SVC (Public Service List) (Service List)); Link to Secure Configuration Guidance; Overview of documentation supplied by the provider for the cloud service offering; Link to Trust Center landing page that includes instructions on accessing information in the trust center; Next Ongoing Certification Report date (see CCM-OCR-NRD (Next Report Date)); Current FedRAMP Recognized independent assessment service", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-SVC", + "name": "Public Service List", + "description": "Providers MUST publicly share a detailed list of specific services and their security categories that are included in the cloud service offering using clear feature or service names that align with standard public marketing materials; this list MUST be complete enough for a potential customer to determine which services are and are not included in the FedRAMP Minimum Assessment Scope without requesting access to underlying FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-FID", + "name": "Always Include FedRAMP ID", + "description": "Providers MUST always include the FedRAMP ID of the related cloud service offering in all FedRAMP Certification Data once assigned, including all reports, notifications, and other communication that results from FedRAMP rules.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-FRC", + "name": "FedRAMP Certification Reports", + "description": "Providers MUST include FedRAMP Certification Reports with their FedRAMP Certification Data without inappropriate modifications, and make such reports available within 2 weeks of receiving the materials from FedRAMP.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-AVR", + "name": "Availability Reporting", + "description": "Providers with Class C Certifications MUST maintain a web service, available to all necessary parties, that indicates current and historical availability of core services within the cloud service offering over at least the past 30 days, including availability incidents, in both human-readable and machine-readable formats; this service MUST be available even if the primary cloud service offering is unavailable.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-UTC", + "name": "Use Trust Centers", + "description": "Providers MUST use a FedRAMP-compatible trust center to store and share FedRAMP Certification Data with all necessary parties.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-CBF", + "name": "Consistency Between Formats", + "description": "Providers MUST use automation to ensure information remains consistent between human-readable and machine-readable formats when FedRAMP Certification Data is provided in both formats.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-RIS", + "name": "Responsible Information Sharing", + "description": "Providers MUST provide sufficient information in FedRAMP Certification Data to support agency authorization decisions but SHOULD NOT include sensitive information that would likely enable a threat actor to gain unauthorized access, cause harm, disrupt operations, or otherwise have a negative adverse impact on the cloud service offering.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-IRP", + "name": "Include Relevant Policies", + "description": "Providers MUST supply all relevant policies and procedures in the FedRAMP Certification Data, including a human-readable and machine-readable reference that explains at least the following about each included policy and procedure: Name of policy or procedure; Name of file, document, web page, etc.; Brief summary of policy or procedure; Word count of document; Current version; Date of last update; Related FedRAMP Practices (if applicable)", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-HAD", + "name": "Historical FedRAMP Certification Data", + "description": "Providers MUST supply snapshots of FedRAMP Certification Data aligned to Ongoing Certification Reports to all necessary parties; these snapshots MUST be available for the duration of FedRAMP Certification.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-PSM", + "name": "Per-Service Certification Materials", + "description": "Providers with Class C Certifications MAY supply per-service FedRAMP Certification materials.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-RPS", + "name": "Responsible Public Package Sharing", + "description": "Providers MAY responsibly share some or all of the information in a FedRAMP Certification Package publicly or with other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-USH", + "name": "Uninterrupted Sharing", + "description": "Trust centers MUST share FedRAMP Certification Data with all necessary parties without interruption.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-PAC", + "name": "Programmatic Access", + "description": "Trust centers MUST provide documented programmatic access to all FedRAMP Certification Data, including programmatic access to human-readable materials.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-AAI", + "name": "Agency Access Inventory", + "description": "Trust centers MUST maintain an inventory and history of federal agency users or systems with access to FedRAMP Certification Data and MUST make this information available to FedRAMP upon request.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-ACL", + "name": "Access Logging", + "description": "Trust centers MUST log access to FedRAMP Certification Data and store summaries of access for at least six months; such information, as it pertains to specific parties, SHOULD be made available upon request by those parties.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-HMR", + "name": "Human and Machine-Readable Certification Data", + "description": "Trust centers SHOULD make FedRAMP Certification Data available to view and download in both human-readable and machine-readable formats.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-SSM", + "name": "Self-Service Access Management", + "description": "Trust centers SHOULD include features that encourage all necessary parties to provision and manage access to FedRAMP Certification Data for their users and services directly.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-UTC-AAD", + "name": "Agency Access Denial", + "description": "Providers MUST notify FedRAMP within 5 business days of denying an agency access request for FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "UTC: Using a Trust Center", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-UTC-AGA", + "name": "Agency Access", + "description": "Providers SHOULD supply access to the FedRAMP Certification Package with agencies upon request.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "UTC: Using a Trust Center", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-CMD", + "name": "Cryptographic Module Documentation", + "description": "Providers MUST document the cryptographic modules used in each service (or groups of services that use the same modules) where cryptographic services are used to protect federal customer data, including whether these modules are validated under the NIST Cryptographic Module Validation Program or are update streams of such modules.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-UVM", + "name": "Using Validated Cryptographic Modules", + "description": "Providers with Class C Certifications SHOULD use cryptographic modules or update streams of cryptographic modules with active validations under the NIST Cryptographic Module Validation Program when using cryptographic services to protect federal customer data.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "elbv2_listener_fips_tls_enabled", + "transfer_server_fips_security_policy_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-CAT", + "name": "Configuration of Agency Tenants", + "description": "Providers SHOULD configure agency tenants by default to use cryptographic services that use cryptographic modules or update streams of cryptographic modules with active validations under the NIST Cryptographic Module Validation Program when such modules are available.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-OVR", + "name": "Overview of the Cloud Service Offering", + "description": "Providers MUST supply a Certification Package Overview within their FedRAMP Certification Package, in both human-readable and JSON formats, that includes at least all of the information required by the following rules: Certification Package Overview: CPO-CSO-MTD (Certification Package Overview Metadata); Certification Data Sharing: CDS-CSO-PUB (Public Information); Certification Data Sharing: CDS-CSO-SVC (Public Service List); Certification Data Sharing: CDS-CSO-IRP (Include Relevant Policies); Minimum Assessment Scope: MAS-CSO-IIR (Identify Information Resources); Minimum Assessment Scope: MAS-CSO-FLO (Information Flows and Security Categories); Minimum Assessment Scope: MAS-CSO-TPR (Third-Party Information Resources); Using Cryptographic Modules: CMU-CSO-CMD (Cryptographic Module Documentation); Independent Verification and Validation: IVV-CSO-ICP (Inclusion in Certification Package)", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-MTD", + "name": "Certification Package Overview Metadata", + "description": "Providers MUST also include the following basic metadata in their Certification Package Overview: Name, title, and contact information of official that is responsible and accountable for the FedRAMP Certification Package; Version; Date and time of last update; Source of update", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-OSA", + "name": "Overall Summary of Assessment in Certification Package", + "description": "Providers seeking Class C Certification MUST also include the overall summary of their FedRAMP independent assessment, supplied by the assessor per IVV-IAS-OSA (Overall Summary of Assessment), in their Certification Package Overview.", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSX-CPM", + "name": "Certification Package Maintenance for 20x", + "description": "Providers with 20x Class C Certifications MUST persistently maintain their FedRAMP Certification Package to ensure it is up to date and complete at least once every 2 weeks.", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-FCP", + "name": "FedRAMP Certification Profile", + "description": "Providers MUST identify a target FedRAMP Certification Profile and apply all relevant FedRAMP Practices to the cloud service offering.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-PKG", + "name": "FedRAMP Certification Package", + "description": "Providers seeking a Certification MUST supply a complete FedRAMP Certification Package to FedRAMP for initial certification; the FedRAMP Certification Package MUST include at least the following information: Information about the Cloud Service Offering following CPO-CSO-OVR (Overview of the Cloud Service Offering); Implementation, Validation, and Assessment information for each relevant FedRAMP requirement/control/ksi as defined in SDR-CSO-FRR (FedRAMP Rules); A real or example Ongoing Certification Report following CCM-OCR-AVL (Report Availability)", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-JSN", + "name": "FedRAMP JSON Schemas", + "description": "Providers MUST supply machine-readable information in JSON documents that are valid against the corresponding JSON schema when a rule contains a FedRAMP JSON schema, UNLESS otherwise specified in the rule.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-MRA", + "name": "Maintain Responsibility and Accountability", + "description": "Providers MUST maintain responsibility and accountability for the accuracy and completeness of all information in the FedRAMP Certification Package, especially when they engage a third party (such as an independent assessor, advisory service, or external tools) to supply information on their behalf.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-POP", + "name": "Pick One Program Certification Type", + "description": "Providers MUST NOT seek both FedRAMP Rev5 Program Certification and FedRAMP 20x Program Certification for the same cloud service offering; pick one type.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-MLF", + "name": "Marketplace Listing First", + "description": "Providers MUST be listed in the FedRAMP Marketplace before applying for FedRAMP Certification, including: FedRAMP Marketplace: MKT-CSO-MLR (Marketplace Listing Requirements); FedRAMP Marketplace: MKT-CSO-PML (Provider Marketplace Listing Requests); FedRAMP Marketplace: MKT-IIP-AGU (Agency Use Cases); FedRAMP Marketplace: MKT-IIP-DCP (Demonstrating Continuous Progress)", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-AFC", + "name": "Applying for FedRAMP Certification", + "description": "Providers MUST complete the FedRAMP Certification Application Form in full to request an initial assessment by FedRAMP.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-FCP", + "name": "Fresh FedRAMP Certification Package", + "description": "Providers MUST supply a fresh initial FedRAMP Certification Package that shows the current status of the cloud service offering as verified and validated by the provider within the previous 7 days.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-FIA", + "name": "Fresh Independent Assessment", + "description": "Providers seeking Class C Certification MUST supply a fresh initial FedRAMP independent assessment that was completed by a FedRAMP Recognized independent assessment service within the previous 3 months.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-NTP", + "name": "No Third-Party Applicants", + "description": "Providers MUST NOT use a third party to apply for a FedRAMP Certification on their behalf; this includes independent assessment services.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-USA", + "name": "Updating Stale Assessments", + "description": "Providers MAY freshen a stale initial independent verification and validation assessment by having a FedRAMP Recognized independent assessment service review any changes between the original assessment and the current status of the cloud service offering in place of a full re-assessment, UNLESS the stale assessment is more than 9 months old.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-VVK", + "name": "Automated Verification and Validation of Key Security Indicators", + "description": "Providers seeking 20x Class C Certification MUST implement automated methods to persistently verify and validate the accuracy and completeness of Key Security Indicators with at least 2 automated methods for each Key Security Indicator.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-MOT", + "name": "Metrics Over Time for Key Security Indicators", + "description": "Providers seeking 20x Class C Certification MUST supply historical metrics including status from persistent validation over at least the past 6 months for all Key Security Indicators.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-VVR", + "name": "Automated Verification and Validation of FedRAMP Rules", + "description": "Providers seeking 20x Class C Certification SHOULD implement automated methods to persistently verify and validate the accuracy and completeness of the Security Decision Record for FedRAMP rules when applicable.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-MAS", + "name": "Application within MAS", + "description": "Providers SHOULD apply ALL Key Security Indicators to ALL aspects of their cloud service offering that are within the FedRAMP Minimum Assessment Scope.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-EFR", + "name": "Evaluate FedRAMP Reportability", + "description": "Providers MUST promptly evaluate incidents to determine if they affect confidentiality or integrity of federal customer data or are likely to affect confidentiality or integrity of federal customer data; such incidents are FedRAMP Reportable Incidents and must be reported following the FedRAMP Incident Evaluation and Communication rules.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-DPR", + "name": "Default PAIN Rating", + "description": "Providers MUST treat FedRAMP Reportable Incidents as if they have a Potential Agency Impact N-rating (PAIN) of 5 UNLESS they promptly estimate the PAIN rating following the rule in IEC-CSO-EFI (Estimate Federal Impact).", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-IIR", + "name": "Initial Incident Report", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties after identifying FedRAMP Reportable Incidents by providing an Initial Incident Report with as much of the following information that is available at the time of reporting and/or the current relevant status for each item: Contact information for the federal incident response coordinator.; Provider's internally assigned tracking identifier; Description of the incident; Timeline of the incident, including start time, time and source of detection, time of completed FedRAMP Reportable Incident evaluation, and other major incident milestones determined by the provider; Historically and currently estimated Potential Agency Impact N-rating (PAIN) of the incident, including an explanation of the evaluation following the requirements in IEC-CSO-EFI (Estimate Federal Impact) (if applicable); Functional impact to federal agency customers (include impact to confidentiality and/or integrity and the impacted federal customer data types); Estimated recovery plan, milestones, and timelines; List of likely affected customer agencies; N1 Initial Incident Report: 1 bizdays; N2 Initial Incident Report: 24 hours; N3 Initial Incident Report: 1 hours; N4 Initial Incident Report: 1 hours; N5 Initial Incident Report: 1 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-OIR", + "name": "Ongoing Incident Reports", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties of ongoing activity as new information becomes available during incident response for FedRAMP Reportable Incidents, including updates (or lack of updates) to all previously reported information and as much of the following additional information that is available and/or the current relevant status for each item: Observed incident activity; Indicators of compromise; Related Common Vulnerabilities and Exposures (CVE) identifier, if applicable; Root cause; Response and recovery activities; N1 Ongoing Incident Report: 1 bizdays; N2 Ongoing Incident Report: 24 hours; N3 Ongoing Incident Report: 6 hours; N4 Ongoing Incident Report: 6 hours; N5 Ongoing Incident Report: 6 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-FIR", + "name": "Final Incident Report", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties by providing a Final Incident Report once the incident has been resolved and recovery is complete, including final updates to all previously reported information. N1 Final Incident Report: 1 bizdays; N2 Final Incident Report: 1 bizdays; N3 Final Incident Report: 6 hours; N4 Final Incident Report: 6 hours; N5 Final Incident Report: 6 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-EFI", + "name": "Estimate Federal Impact", + "description": "Providers SHOULD promptly estimate the likely adverse impact of an incident on agency customers to assign a Potential Agency Impact N-rating; this step is called Incident Rating. N1 for a likely minimal customer effect on 1 or more agencies.; N2 for a likely narrow customer effect on 1 or more agencies.; N3 for a likely disruptive customer effect on 1 agency.; N4 for a likely debilitating customer effect on 1 agency or a likely disruptive customer effect on more than 1 agency.; N5 for a likely debilitating customer effect on more than 1 agency.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-AIR", + "name": "Automated Incident Reporting", + "description": "Providers SHOULD use automation to minimize human intervention in the process of reporting FedRAMP Reportable Incidents to all affected parties.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-FIA", + "name": "FedRAMP Independent Assessments", + "description": "Providers with Class C Certifications MUST persistently complete an independent verification and validation assessment of all applicable FedRAMP rules with a FedRAMP Recognized independent assessment service OR FedRAMP at least once per year; this is a FedRAMP independent assessment.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-SEI", + "name": "Supply Evidence of Implementation", + "description": "Providers MUST supply evidence to all necessary assessors of the implementation of the measures that have been documented to meet FedRAMP Practices; this evidence is the result of verification.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-SEE", + "name": "Supply Evidence of Effectiveness", + "description": "Providers MUST supply evidence to all necessary assessors of the effectiveness of the measures that have been implemented to meet FedRAMP Practices; this evidence is the result of validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-ICP", + "name": "Inclusion in Certification Package", + "description": "Providers MUST supply the results of FedRAMP independent assessments in their FedRAMP Certification Package without inappropriate modification.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-DUS", + "name": "Document Use of Representative Samples", + "description": "Providers MUST document and explain the use of representative samples during verification and validation when using representative samples as allowed by IVV-CSO-USR (Use Representative Samples).", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-STE", + "name": "Supply Technical Explanations", + "description": "Providers SHOULD supply all necessary assessors with technical explanations, demonstrations, and other relevant supporting information about the technical capabilities they employ to address FedRAMP rules; this SHOULD be supplied as necessary to ensure the assessor can effectively complete verification and validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-USR", + "name": "Use Representative Samples", + "description": "Providers MAY use representative samples as appropriate during verification and validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-RAA", + "name": "Receiving Assessor Advice", + "description": "Providers MAY ask for and accept advice from their assessor during assessment regarding techniques and procedures that will improve their security posture or the effectiveness, clarity, and accuracy of their verification, validation and reporting procedures, UNLESS doing so is likely to compromise the objectivity and integrity of the assessment.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSX-AIA", + "name": "Annual Independent Assessments for 20x", + "description": "Providers with 20x Class C Certifications MUST include all Key Security Indicators in a FedRAMP independent assessment at least once per year.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-IIR", + "name": "Identify Information Resources", + "description": "Providers MUST identify a set of information resources to assess for FedRAMP Certification that includes all information resources that are likely to handle federal customer data or likely to impact the confidentiality, integrity, or availability of federal customer data handled by the cloud service offering; this set of information resources is the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled", + "resourceexplorer2_indexes_found" + ], + "azure": [], + "gcp": [ + "iam_cloud_asset_inventory_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "MAS-CSO-FLO", + "name": "Information Flows and Security Categories", + "description": "Providers MUST clearly identify, document, and explain information flows and security categories for ALL information resources or sets of information resources in the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-TPR", + "name": "Third-Party Information Resources", + "description": "Providers MUST address the potential impact to federal customer data from third-party information resources used by the cloud service offering, ONLY IF MAS-CSO-IIR (Identify Information Resources) APPLIES, by documenting the following information about each applicable third-party information resource: General usage and configuration; Explanation or justification for use; Mitigation measures in place to reduce the potential impact to federal customer data; Compensating controls in place to reduce the potential impact to federal customer data", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-MDI", + "name": "Metadata Inclusion", + "description": "Providers MUST include metadata (including metadata about federal customer data) in the Minimum Assessment Scope ONLY IF MAS-CSO-IIR (Identify Information Resources) APPLIES.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-SUP", + "name": "Supplemental Information", + "description": "Providers MAY include additional materials about other information resources that are not part of the cloud service offering in a FedRAMP Certification Package supplement; these resources will not be FedRAMP Certified and MUST be clearly marked and separated from the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-CSO-MLR", + "name": "Marketplace Listing Requirements", + "description": "Providers MUST address at least these FedRAMP rules to apply for a new FedRAMP Marketplace listing OR to request updates to an existing listing: Certification Data Sharing: CDS-CSO-PUB (Public Information)", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-CSO-PML", + "name": "Provider Marketplace Listing Requests", + "description": "Providers MUST notify FedRAMP using the FedRAMP Marketplace Providing Listing Request Form to request a listing in the FedRAMP Marketplace.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-AGU", + "name": "Agency Use Cases", + "description": "Providers MUST demonstrate that a cloud service offering is intended for one of the following use cases: Direct Use: The product will be used directly by agency customers for integration into a federal information system that falls within the scope of 44 USC § 3506 and will receive an agency Authorization to Operate.; Indirect Use: The product will be included as a third-party information resource in other cloud service offerings that are directly used by agency customers.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-DCP", + "name": "Demonstrating Continuous Progress", + "description": "Providers MUST demonstrate continuous progress towards a FedRAMP Certification, documented in their Trust Center or website and updated at least quarterly; progress is measured by the provider against documented goals and milestones.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-DLA", + "name": "Deadline for Assessment", + "description": "Providers MUST demonstrate that an assessment for a FedRAMP Certification Class B, C, or D has been scheduled within 2 years of initial listing in the Initial Implementation Phase.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-RSC", + "name": "Recommended Secure Configuration", + "description": "Providers MUST create, maintain, and make available recommendations for securely configuring their cloud services (the Secure Configuration Guide) that includes at least the following information: Required: Instructions on how to securely access, configure, operate, and decommission top-level administrative accounts that control enterprise access to the entire cloud service offering.; Required: Explanations of security-related settings that can be operated only by top-level administrative accounts and their security implications.; Recommended: Explanations of security-related settings that can be operated only by privileged accounts and their security implications.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-AUP", + "name": "Use Instructions", + "description": "Providers MUST include instructions in the FedRAMP Certification Package that explain how to obtain and use the Secure Configuration Guide.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-PUB", + "name": "Public Secure Configuration Guidance", + "description": "Providers SHOULD make the Secure Configuration Guide available publicly.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-SDF", + "name": "Secure Defaults", + "description": "Providers SHOULD set all settings to their recommended secure defaults for top-level administrative accounts and privileged accounts when initially provisioned.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-CMP", + "name": "Comparison Capability", + "description": "Providers SHOULD offer the capability to compare all current settings for top-level administrative accounts and privileged accounts to the recommended secure defaults.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-EXP", + "name": "Export Capability", + "description": "Providers SHOULD offer the capability to export all security settings in a machine-readable format.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-API", + "name": "API Capability", + "description": "Providers SHOULD offer the capability to view and adjust security settings via an API or similar capability.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-MRG", + "name": "Machine-Readable Guidance", + "description": "Providers SHOULD also provide the Secure Configuration Guide in a machine-readable format that can be used by customers or third-party tools to compare against current settings.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-VRH", + "name": "Versioning and Release History", + "description": "Providers SHOULD provide versioning and a release history for recommended secure default settings for top-level administrative accounts and privileged accounts as they are adjusted over time.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-EVA", + "name": "Evaluate Changes", + "description": "Providers MUST evaluate all potential significant changes to determine the type of significant change and follow the appropriate Significant Change Notification rules. Is it a significant change? --> Continue evaluation and follow the Significant Change Notification rules.; If it is, is it an FedRAMP Certification class change? --> This requires a new assessment and cannot be done under the Significant Change Notification rules.; If it is not, is it a routine recurring change? --> Follow the Routine Recurring Change rules (SCN-RTR Routine Recurring Changes).; If it is not, is it a transformative change? --> Follow the Transformative Change rules (SCN-TRF Transformative Changes).; If it is not, then it is an adaptive change --> Follow the Adaptive Change rules (SCN-ADP Adaptive Changes).", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-MAR", + "name": "Maintain Audit Records", + "description": "Providers MUST maintain auditable records of the significant change evaluation activities required by SCN-CSO-EVA (Evaluate Changes) and make them available to FedRAMP as requested.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-INF", + "name": "Required Information", + "description": "Providers MUST include at least the following information in Significant Change Notifications: Service Offering FedRAMP ID; Assessor Name (if applicable); Related Vulnerability (if applicable); Significant Change type and explanation of categorization; Short description of change; Reason for change; Summary of customer impact, including changes to services and customer configuration responsibilities; Plan and timeline for the change, including for the verification, assessment, and/or validation of impacted Key Security Indicators or Rev5 Controls; Copy of the business or security impact analysis; Name and title of approver", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-HIS", + "name": "Historical Notifications", + "description": "Providers MUST keep 12 months of historical Significant Change Notifications available with their FedRAMP Certification Data.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-HRM", + "name": "Human and Machine-Readable Notifications", + "description": "Providers MUST make ALL Significant Change Notifications and related audit records available in human-readable and JSON formats.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-ARI", + "name": "Additional Relevant Information", + "description": "Providers MAY include additional relevant information in Significant Change Notifications.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-NOM", + "name": "Notification Mechanisms", + "description": "Providers MAY notify necessary parties in a variety of ways as long as the mechanism for notification is clearly documented in the FedRAMP Certification Package and easily accessible.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-EMG", + "name": "Emergency Changes", + "description": "Providers MAY execute significant changes (including transformative changes) during an emergency or incident without following the Significant Change Notification rules in advance. In such emergencies, providers MUST follow all relevant procedures, notify all necessary parties, retroactively provide all Significant Change Notification materials, and complete appropriate assessment after the incident.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-ADP-NTF", + "name": "Notification Requirements", + "description": "Providers MUST notify all necessary parties within 10 business days after finishing adaptive changes, also including the following information: Summary of any new risks identified and/or vulnerabilities resulting from the change (if applicable)", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "ADP: Adaptive Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-RTR-NNR", + "name": "No Notification Requirements", + "description": "Providers SHOULD NOT make formal Significant Change Notifications for routine recurring changes; this type of change is exempted from notification requirements.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "RTR: Routine Recurring Changes", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NIP", + "name": "Notification of Initial Plans", + "description": "Providers MUST notify all necessary parties of initial plans for transformative changes at least 30 business days before starting transformative changes, including a summary of any likely security impacts or changes in risk.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NFP", + "name": "Notification of Final Plans", + "description": "Providers MUST notify all necessary parties of final plans for transformative changes at least 10 business days before starting transformative changes, including updates to all previously sent information.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NAF", + "name": "Notification After Finishing", + "description": "Providers MUST notify all necessary parties within 5 business days after finishing transformative changes, including updates to all previously sent information.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NAV", + "name": "Notification After Verification", + "description": "Providers MUST notify all necessary parties within 5 business days after completing the verification, assessment, and/or validation of transformative changes, also including the following information: Updates to all previously sent information; Summary of any new risks identified and/or vulnerabilities resulting from the change (if applicable); Copy of the security assessment report (if applicable)", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-UPD", + "name": "Update Documentation", + "description": "Providers MUST publish updated service documentation and other materials to reflect transformative changes within 30 business days after finishing transformative changes.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-TPR", + "name": "Third-Party Review", + "description": "Providers SHOULD engage a third-party assessor to review the scope and impact of the planned change before starting transformative changes if human validation is necessary; such reviews SHOULD be limited to security decisions that require human validation.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSO-FRR", + "name": "FedRAMP Rules", + "description": "Providers MUST supply a Security Decision Record, in both human-readable and JSON formats, that includes at least all of the following information for each applicable FedRAMP rule: Explanation of how the rule is followed, or an explanation of the reason and resulting risk to customers for not following the rule.; Verification that the implementation is appropriate for the rule, or that the reason for not implementing is accepted by a senior official.; Validation that the implementation is in place and working as intended, or that the reason for not implementing is accepted by a senior official.; Independent verification.; Independent validation.; Any responses or clarifications to the comments in the independent verification or validation.; Rule-specific artifacts (if applicable).", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSO-MTD", + "name": "Security Decision Record Metadata", + "description": "Providers MUST also include the following basic metadata in their Security Decision Record: Version; Date and time of last update; Source of update", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSX-KSI", + "name": "Key Security Indicators", + "description": "Providers MUST also include short and simple high-level summaries of at least the following for each applicable Key Security Indicator: Explanation of measures (and their objectives) that demonstrate the Key Security Indicator, or an explanation of the reason and resulting risk to customers for not having measures available for that Key Security Indicator.; Explanation of the cycle for any measures that are implemented persistently (if applicable).; Verification that the measures demonstrate the Key Security Indicator, or that the reason for not having them is accepted.; Verification that the automation in place is accurate and sufficient to demonstrate appropriate measures for the Key Security Indicator, or that automation is not necessary for each measure.; Validation that the measures are accurately produced and are in place and working as intended, or that the reason for not having them is valid.", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSX-KMT", + "name": "Key Security Indicator Metrics", + "description": "Providers with 20x Class C Certifications MUST also include historical metrics in their Security Decision Record, supplying at least the following information for each applicable Key Security Indicator: Summary of each metric over the past 30 days; Summary of metric up to the past year (where available); All daily metric data up to the past year (where available)", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DET", + "name": "Vulnerability Detection", + "description": "Providers MUST systematically, persistently, and promptly discover and identify vulnerabilities within their cloud service offering using appropriate techniques such as assessment, scanning, threat intelligence, vulnerability disclosure mechanisms, bug bounties, penetration testing, incident response, automated control testing, supply chain monitoring, and other relevant capabilities; this process is called vulnerability detection. Vulnerability detection includes persistently verifying and validating that information resources and processes are operating as intended and documented for FedRAMP Practices.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "ecr_registry_enhanced_scanning_enabled", + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled", + "securityhub_enabled" + ], + "azure": [ + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_container_images_scan_enabled", + "defender_ensure_defender_cspm_is_on", + "sqlserver_va_periodic_recurring_scans_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-CSO-RES", + "name": "Vulnerability Response", + "description": "Providers MUST systematically, persistently, and promptly track, evaluate, monitor, mitigate, remediate, assess exploitation of, report, and otherwise manage all detected vulnerabilities within their cloud service offering; this process is called vulnerability response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "ecr_repositories_scan_vulnerabilities_in_latest_image", + "inspector2_active_findings_exist" + ], + "azure": [ + "defender_container_images_resolved_vulnerabilities" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "ecr_repositories_scan_vulnerabilities_in_latest_image", + "ConfigKey": "ecr_repository_vulnerability_minimum_severity", + "Operator": "eq", + "Value": "MEDIUM", + "Provider": "aws" + } + ] + }, + { + "id": "VDR-CSO-FAV", + "name": "Failures Are Vulnerabilities", + "description": "Providers MUST treat problems or failures with their vulnerability detection and response processes as vulnerabilities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_coverage_scan_status_active" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DFR", + "name": "Design For Resilience", + "description": "Providers SHOULD make design and architecture decisions for their cloud service offering that mitigate the risk of vulnerabilities by default AND decrease the risk and complexity of vulnerability detection and response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-ADT", + "name": "Automate Detection", + "description": "Providers SHOULD use automated services to improve and streamline vulnerability detection and response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ecr_registry_enhanced_scanning_enabled", + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled" + ], + "azure": [ + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_container_images_scan_enabled", + "sqlserver_va_periodic_recurring_scans_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DAC", + "name": "Detect After Changes", + "description": "Providers SHOULD automatically perform vulnerability detection on representative samples of new or significantly changed information resources.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled" + ], + "azure": [ + "defender_container_images_scan_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-MSP", + "name": "Maintain Security", + "description": "Providers SHOULD NOT weaken the security of information resources to facilitate vulnerability scanning, detection, or assessment activities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-AKE", + "name": "Avoid KEVs", + "description": "Providers SHOULD NOT deploy or otherwise activate new machine-based information resources with Known Exploited Vulnerabilities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [ + "inspector2_active_findings_no_known_exploited_vulnerabilities" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-SIR", + "name": "Sampling", + "description": "Providers MAY sample effectively identical information resources, especially machine-based information resources, when performing vulnerability detection UNLESS doing so would decrease the efficiency or effectiveness of vulnerability detection.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-NMV", + "name": "Non-Machine Verification and Validation", + "description": "Providers MUST verify and validate the status of non-machine-based information resources at least once every 3 months.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-PDD", + "name": "Persistent Drift Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on all information resources that are likely to drift, at least once every 14 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned", + "inspector2_is_enabled", + "securityhub_enabled" + ], + "azure": [ + "defender_ensure_defender_cspm_is_on" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 14, + "Provider": "aws" + }, + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-PCD", + "name": "Persistently Complete Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on all information resources that are NOT likely to drift, at least once every month.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 30, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-PVR", + "name": "Mitigation and Remediation Expectations", + "description": "Providers with Class C Certifications SHOULD partially mitigate vulnerabilities, fully mitigate vulnerabilities, or remediate vulnerabilities to a lower Potential Agency Impact N-rating within the timeframes from evaluation shown below, factoring for the current Potential Agency Impact N-rating as defined in VER-EVA-EPA (Estimate Potential Agency Impact), internet reachability, and likely exploitability: N2 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 48 days; N2 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 128 days; N2 Not Likely Exploitable Vulnerability: 192 days; N3 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 16 days; N3 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 32 days; N3 Not Likely Exploitable Vulnerability: 128 days; N4 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 4 days; N4 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 8 days; N4 Not Likely Exploitable Vulnerability: 64 days; N5 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 2 days; N5 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 4 days; N5 Not Likely Exploitable Vulnerability: 16 days", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-RMN", + "name": "Remaining Vulnerabilities", + "description": "Providers SHOULD mitigate or remediate remaining vulnerabilities during routine operations as determined necessary by the provider.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ssm_managed_compliant_patching" + ], + "azure": [ + "defender_ensure_system_updates_are_applied" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-KEV", + "name": "Remediate KEVs", + "description": "Providers SHOULD remediate Known Exploited Vulnerabilities according to the due dates in the CISA Known Exploited Vulnerabilities Catalog (even if the vulnerability has been fully mitigated) as required by CISA Binding Operational Directive (BOD) 26-04 or any successor guidance from CISA.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_active_findings_kev_within_due_date" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-PSD", + "name": "Persistent Sample Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on representative samples of similar machine-based information resources, at least once every 3 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 3, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-MVX", + "name": "Persistent Machine Verification and Validation for 20x", + "description": "Providers of FedRAMP 20x Class C offerings MUST verify and validate the status of machine-based information resources at least once every 3 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled", + "inspector2_coverage_recently_scanned", + "securityhub_enabled" + ], + "azure": [ + "defender_ensure_defender_cspm_is_on" + ], + "gcp": [ + "iam_cloud_asset_inventory_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 3, + "Provider": "aws" + }, + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VER-EVA-ELX", + "name": "Evaluate Exploitability", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are likely exploitable vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_is_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EIR", + "name": "Evaluate Internet-Reachability", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are internet-reachable vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_is_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EPA", + "name": "Estimate Potential Agency Impact", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to estimate the potential agency impact of exploitation on government customers AND assign one of the following Potential Agency Impact N-ratings (PAIN): N1: Exploitation could be expected to have minimal customer effects on one or more agencies that use the cloud service offering.; N2: Exploitation could be expected to have narrow customer effects on one or more agencies that use the cloud service offering.; N3: Exploitation could be expected to have a disruptive customer effect on one agency that uses the cloud service offering.; N4: Exploitation could be expected to have a debilitating customer effect on one agency that uses the cloud service offering OR a disruptive customer effect on more than one federal agency that uses the cloud service offering.; N5: Exploitation could be expected to have a debilitating customer effect on more than one agency that uses the cloud service offering.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-AIA", + "name": "Assume It's Automatable", + "description": "Providers MUST assume the exploitation of vulnerabilities can be automated UNLESS they have evidence proving otherwise.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-GRV", + "name": "Group Vulnerabilities", + "description": "Providers SHOULD evaluate detected vulnerabilities, considering the context of the cloud service offering, to identify logical groupings of affected information resources that may improve the efficiency and effectiveness of vulnerability response by consolidating further activity; FedRAMP Vulnerability Detection and Response rules are then applied to these consolidated groupings of vulnerabilities instead of each individual detected instance.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EFP", + "name": "Evaluate False Positives", + "description": "Providers SHOULD evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are false positive vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EFA", + "name": "Evaluation Factors", + "description": "Providers SHOULD consider at least the following factors when considering the context of the cloud service offering to evaluate detected vulnerabilities: Criticality: How important are the systems or information that might be impacted by the vulnerability?; Reachability: How might a threat actor reach the vulnerability and how likely is that?; Exploitability: How easy is it for a threat actor to exploit the vulnerability and how likely is that?; Detectability: How easy is it for a threat actor to become aware of the vulnerability and how likely is that?; Prevalence: How much of the cloud service offering is affected by the vulnerability?; Privilege: How much privileged authority or access is granted or can be gained from exploiting the vulnerability?; Proximate Vulnerabilities: How does this vulnerability interact with previously detected vulnerabilities, especially partially or fully mitigated vulnerabilities?; Known Threats: How might already known threats leverage the vulnerability and how likely is that?", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-PER", + "name": "Persistent Reporting", + "description": "Providers MUST report vulnerability detection and response activity (including persistent verification and validation) to all necessary parties persistently, summarizing ALL activity since the previous report; these reports are FedRAMP Certification Data and are subject to FedRAMP Certification Data Sharing rules.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-VDT", + "name": "Vulnerability Details", + "description": "Providers MUST include the following information (if applicable) on detected vulnerabilities when reporting on vulnerability detection and response activity, UNLESS it is an accepted vulnerability: Provider's internally assigned tracking identifier; Time and source of the detection; Time of completed evaluation; Is it an internet-reachable vulnerability or not?; Is it a likely exploitable vulnerability or not?; Historically and currently estimated Potential Agency Impact N-rating of exploitation; Time and Potential Agency Impact N-rating of each completed and evaluated reduction in Potential Agency Impact N-rating; Estimated time and target Potential Agency Impact N-rating of next reduction in Potential Agency Impact N-rating; Is it currently or is it likely to become an overdue vulnerability or not? If so, explain.; Any supplementary information the provider responsibly determines will help federal agencies assess or mitigate the risk to their federal customer data within the cloud service offering resulting from the vulnerability; Final disposition of the vulnerability", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-AVI", + "name": "Accepted Vulnerability Info", + "description": "Providers MUST include the following information on accepted vulnerabilities when reporting on vulnerability detection and response activity: Provider's internally assigned tracking identifier; Time and source of the detection; Time of completed evaluation; Is it an internet-reachable vulnerability or not?; Is it a likely exploitable vulnerability or not?; Currently estimated Potential Agency Impact N-rating; Explanation of why this is an accepted vulnerability; Any supplementary information the provider determines will responsibly help federal agencies assess or mitigate the risk to their federal customer data within the cloud service offering resulting from the accepted vulnerability", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-NID", + "name": "Responsible Disclosure", + "description": "Providers MUST NOT irresponsibly disclose specific sensitive information about vulnerabilities that would likely lead to exploitation, but MUST disclose sufficient information for informed risk-based decision-making to all necessary parties.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-HLO", + "name": "High-Level Overviews", + "description": "Providers SHOULD include high-level overviews of ALL vulnerability detection and response activities conducted during this period for the cloud service offering; this includes vulnerability disclosure programs, bug bounty programs, penetration testing, assessments, etc.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-RPD", + "name": "Responsible Public Disclosure", + "description": "Providers MAY responsibly disclose vulnerabilities publicly or with other parties if the provider determines doing so will NOT likely lead to exploitation.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-MHR", + "name": "Monthly Activity Report", + "description": "Providers MUST report vulnerability detection and response activity to all necessary parties in a consistent format that is human readable at least monthly.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-MAV", + "name": "Mark Accepted Vulnerabilities", + "description": "Providers MUST categorize any vulnerability that is not or will not be fully mitigated or remediated within 192 days of evaluation as an accepted vulnerability.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_active_findings_within_max_age" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_active_findings_within_max_age", + "ConfigKey": "inspector2_active_finding_max_age_days", + "Operator": "lte", + "Value": 192, + "Provider": "aws" + } + ] + }, + { + "id": "VER-TFR-MRH", + "name": "Historical Activity", + "description": "Providers with Class C Certifications SHOULD make all recent historical vulnerability detection and response activity available in JSON format for automated retrieval by all necessary parties (e.g. using an API service or similar); this information SHOULD be updated persistently, at least once every 14 days.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-EVU", + "name": "Evaluate Vulnerabilities Quickly", + "description": "Providers with Class C Certifications SHOULD evaluate ALL vulnerabilities as required by VER-EVA (Evaluation) within 5 days of detection.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-IRI", + "name": "Internet-Reachable Incidents", + "description": "Providers with Class C Certifications SHOULD treat internet-reachable likely exploitable vulnerabilities where Potential Agency Impact N-rating > 3 as a FedRAMP Reportable Incident until they are partially mitigated vulnerabilities at N3 or below.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-NRI", + "name": "Non-Internet-Reachable Incidents", + "description": "Providers with Class C Certifications MAY treat likely exploitable vulnerabilities that are NOT internet-reachable where Potential Agency Impact N-rating = 5 as a FedRAMP Reportable Incident until they are partially mitigated vulnerabilities at N4 or below.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + } + ] +} diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 46127c9699..0c7551d634 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -190,6 +190,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/prowler/config/schema/aws.py b/prowler/config/schema/aws.py index 75fa5f73c0..c46d848650 100644 --- a/prowler/config/schema/aws.py +++ b/prowler/config/schema/aws.py @@ -333,6 +333,20 @@ class AWSProviderConfig(ProviderConfigBase): description="Highest severity tolerated for ECR images.", ) + # --- Inspector2 ------------------------------------------------------- + inspector2_max_days_since_last_scan: Optional[int] = Field( + default=None, + ge=1, + le=90, + description="Days since Inspector2 last scanned a covered resource. Range: 1..90.", + ) + inspector2_active_finding_max_age_days: Optional[int] = Field( + default=None, + ge=1, + le=365, + description="Days an Inspector2 finding can stay active since first observed. Range: 1..365.", + ) + # --- Trusted Advisor -------------------------------------------------- verify_premium_support_plans: Optional[bool] = None diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json new file mode 100644 index 0000000000..9e321f7c54 --- /dev/null +++ b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "elbv2_listener_fips_tls_enabled", + "CheckTitle": "ELBv2 HTTPS/TLS listeners use a FIPS TLS security policy", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "elbv2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "low", + "ResourceType": "AwsElbv2LoadBalancer", + "ResourceGroup": "network", + "Description": "**ELBv2 HTTPS and TLS listeners** are assessed for use of a **FIPS** TLS security policy (`ELBSecurityPolicy-*-FIPS-*`). FIPS policies terminate TLS with the AWS-LC FIPS validated cryptographic module.", + "Risk": "Listeners without a FIPS policy terminate TLS with cryptographic modules that are not FIPS 140 validated, which does not meet requirements to protect federal or regulated data with **NIST CMVP validated cryptography**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/describe-ssl-policies.html", + "https://docs.aws.amazon.com/elasticloadbalancing/latest/network/describe-ssl-policies.html", + "https://aws.amazon.com/compliance/fips/" + ], + "Remediation": { + "Code": { + "CLI": "aws elbv2 modify-listener --listener-arn --ssl-policy ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::ElasticLoadBalancingV2::Listener\n Properties:\n LoadBalancerArn: \n Protocol: HTTPS\n Port: 443\n DefaultActions:\n - Type: forward\n TargetGroupArn: \n Certificates:\n - CertificateArn: \n SslPolicy: ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04 # FIX: uses a FIPS TLS policy\n```", + "Other": "1. In the AWS Console, go to EC2 > Load Balancers\n2. Select the load balancer and open the Listeners tab\n3. Select each HTTPS/TLS listener and choose Edit\n4. Set Security policy to a FIPS policy such as ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04\n5. Save changes", + "Terraform": "```hcl\nresource \"aws_lb_listener\" \"\" {\n load_balancer_arn = \"\"\n port = 443\n protocol = \"HTTPS\"\n ssl_policy = \"ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04\" # FIX: FIPS TLS policy\n certificate_arn = \"\"\n\n default_action {\n type = \"forward\"\n target_group_arn = \"\"\n }\n}\n```" + }, + "Recommendation": { + "Text": "Use a **FIPS** TLS security policy, such as `ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04`, on every HTTPS and TLS listener that carries federal or regulated data.", + "Url": "https://hub.prowler.com/check/elbv2_listener_fips_tls_enabled" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [ + "elbv2_insecure_ssl_ciphers", + "elbv2_listener_pqc_tls_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py new file mode 100644 index 0000000000..3a9d07f4ba --- /dev/null +++ b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py @@ -0,0 +1,35 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.elbv2.elbv2_client import elbv2_client + + +class elbv2_listener_fips_tls_enabled(Check): + """Ensure every ELBv2 HTTPS or TLS listener uses a FIPS TLS security policy.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each load balancer terminates HTTPS/TLS with a FIPS policy.""" + findings = [] + for lb in elbv2_client.loadbalancersv2.values(): + if lb.listener_discovery_failed: + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=lb) + tls_listeners = { + listener_arn: listener + for listener_arn, listener in lb.listeners.items() + if listener.protocol in ("HTTPS", "TLS") + } + non_fips_listeners = [ + f"{listener.protocol}:{listener.port} ({listener_arn}) uses {listener.ssl_policy or ''}" + for listener_arn, listener in tls_listeners.items() + if "FIPS" not in (listener.ssl_policy or "").split("-") + ] + if not tls_listeners: + report.status = "PASS" + report.status_extended = f"ELBv2 {lb.name} has no HTTPS/TLS listeners." + elif non_fips_listeners: + report.status = "FAIL" + report.status_extended = f"ELBv2 {lb.name} has HTTPS/TLS listeners without a FIPS TLS security policy: {', '.join(non_fips_listeners)}." + else: + report.status = "PASS" + report.status_extended = f"ELBv2 {lb.name} has all HTTPS/TLS listeners using a FIPS TLS security policy." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json new file mode 100644 index 0000000000..3795a96fae --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_kev_within_due_date", + "CheckTitle": "Inspector2 has no active findings for CISA Known Exploited Vulnerabilities past their remediation due date", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "critical", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings for **CISA Known Exploited Vulnerabilities** are compared with the remediation due date (`dateDue`) that CISA assigns to each entry of the KEV catalog. Findings that are still active after that date are reported.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "CISA due dates reflect **active exploitation**. Missing them keeps exploited vulnerabilities open beyond the window CISA sets for federal agencies and shows that vulnerability response is not keeping pace with real threats.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the AWS Console, open Amazon Inspector > Findings\n2. Filter by Vulnerability ID for each overdue CVE reported by this check\n3. Patch or upgrade the affected packages, rebuild container images or update Lambda runtimes\n4. If a fix is not available, apply the mitigations listed in the CISA catalog entry\n5. Confirm the findings move to Closed", + "Terraform": "" + }, + "Recommendation": { + "Text": "Track every KEV finding against its **CISA due date** and remediate before it passes. When no fix exists yet, apply the vendor or CISA mitigations and document the residual risk.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_kev_within_due_date" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_no_known_exploited_vulnerabilities" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py new file mode 100644 index 0000000000..e0ec8ddd30 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py @@ -0,0 +1,66 @@ +from datetime import datetime, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) +from prowler.providers.aws.services.inspector2.lib.vulnerabilities import ( + summarize_vulnerabilities, +) + + +class inspector2_active_findings_kev_within_due_date(Check): + """Ensure active Inspector2 findings for CISA KEVs are not past their CISA due date.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any CISA KEV finding is past its remediation due date.""" + findings = [] + now = datetime.now(timezone.utc) + known_exploited = inspector2_client.known_exploited_vulnerabilities + lookup_failed = inspector2_client.vulnerability_lookup_failed + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + vulnerability_ids = { + finding.vulnerability_id + for finding in inspector.findings + if finding.vulnerability_id + } + overdue = sorted( + f"{vulnerability_id} (due {known_exploited[vulnerability_id].date_due.date().isoformat()})" + for vulnerability_id in known_exploited.keys() & vulnerability_ids + if known_exploited[vulnerability_id].date_due + and known_exploited[vulnerability_id].date_due < now + ) + unverified_ids = sorted(vulnerability_ids & lookup_failed) + if overdue: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities past their remediation due date: " + f"{summarize_vulnerabilities(overdue)}." + ) + elif unverified_ids: + report.status = "MANUAL" + report.status_extended = ( + "Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of " + f"{summarize_vulnerabilities(unverified_ids)} in region {inspector.region}; " + "verify the inspector2:BatchGetFindingDetails permission." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities past their remediation due date." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json new file mode 100644 index 0000000000..5072ebd6a6 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_no_known_exploited_vulnerabilities", + "CheckTitle": "Inspector2 has no active findings for CISA Known Exploited Vulnerabilities", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "high", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings are cross-referenced with the **CISA Known Exploited Vulnerabilities (KEV)** catalog, using the CISA data that Inspector returns in the finding details (`BatchGetFindingDetails`) of each CVE.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "KEV entries are vulnerabilities **confirmed as exploited in the wild**. Workloads carrying them are prime targets for initial access and ransomware, enabling remote code execution, data exfiltration and lateral movement.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the AWS Console, open Amazon Inspector > Findings\n2. Filter by Vulnerability ID for each CVE reported by this check\n3. Patch or upgrade the affected packages, rebuild container images or update Lambda runtimes\n4. Confirm the findings move to Closed", + "Terraform": "" + }, + "Recommendation": { + "Text": "Remediate KEV findings before any other vulnerability: patch or upgrade the affected packages, rebuild and redeploy container images, and stop deploying new resources that carry **known exploited vulnerabilities**.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_no_known_exploited_vulnerabilities" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_exist", + "inspector2_active_findings_kev_within_due_date" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py new file mode 100644 index 0000000000..e483205cb1 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py @@ -0,0 +1,57 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) +from prowler.providers.aws.services.inspector2.lib.vulnerabilities import ( + summarize_vulnerabilities, +) + + +class inspector2_active_findings_no_known_exploited_vulnerabilities(Check): + """Ensure no active Inspector2 finding is a CISA Known Exploited Vulnerability.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any active finding is a CISA Known Exploited Vulnerability.""" + findings = [] + known_exploited = inspector2_client.known_exploited_vulnerabilities + lookup_failed = inspector2_client.vulnerability_lookup_failed + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + vulnerability_ids = { + finding.vulnerability_id + for finding in inspector.findings + if finding.vulnerability_id + } + kev_ids = sorted(known_exploited.keys() & vulnerability_ids) + unverified_ids = sorted(vulnerability_ids & lookup_failed) + if kev_ids: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has active findings in region {inspector.region} for CISA " + f"Known Exploited Vulnerabilities: {summarize_vulnerabilities(kev_ids)}." + ) + elif unverified_ids: + report.status = "MANUAL" + report.status_extended = ( + "Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of " + f"{summarize_vulnerabilities(unverified_ids)} in region {inspector.region}; " + "verify the inspector2:BatchGetFindingDetails permission." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json new file mode 100644 index 0000000000..7846da4f05 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_within_max_age", + "CheckTitle": "Inspector2 has no active findings older than the configured maximum age", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/Patch Management", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings are evaluated against the configurable `inspector2_active_finding_max_age_days` threshold (192 days by default), using the time since each finding was first observed (`firstObservedAt`). Suppressed and closed findings are not active and are not evaluated.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "Findings left open for months show that **vulnerability response** is not keeping up. Long-lived vulnerabilities give attackers time to discover and exploit them, and a backlog that is neither fixed nor formally accepted hides real risk from decision makers.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/findings-understanding.html", + "https://docs.aws.amazon.com/inspector/latest/user/findings-managing-supression-rules.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, open Findings and filter by Finding status = Active\n2. Remediate the findings first observed longest ago\n3. For vulnerabilities you formally accept, choose Suppression rules in the navigation pane and create a rule so they stop counting as active", + "Terraform": "" + }, + "Recommendation": { + "Text": "Remediate findings within your vulnerability response timeframes. Vulnerabilities you decide not to fix should be formally **accepted** and suppressed with a documented justification instead of staying active indefinitely.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_within_max_age" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_exist" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py new file mode 100644 index 0000000000..220ee3c9cd --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py @@ -0,0 +1,51 @@ +from datetime import datetime, timedelta, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + + +class inspector2_active_findings_within_max_age(Check): + """Ensure no Inspector2 finding stays active longer than the configured days.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any active finding is older than the allowed days.""" + findings = [] + max_age_days = inspector2_client.audit_config.get( + "inspector2_active_finding_max_age_days", 192 + ) + max_age = timedelta(days=max_age_days) + now = datetime.now(timezone.utc) + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + stale_ages = [ + now - finding.first_observed_at + for finding in inspector.findings + if finding.first_observed_at + and now - finding.first_observed_at > max_age + ] + if stale_ages: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has {len(stale_ages)} active findings in region {inspector.region} " + f"first observed more than {max_age_days} days ago, the oldest {max(stale_ages).days} days ago." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} " + f"first observed more than {max_age_days} days ago." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json new file mode 100644 index 0000000000..8fc174f17f --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_coverage_recently_scanned", + "CheckTitle": "Inspector2 covered resource was scanned within the configured number of days", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** coverage is evaluated for every actively monitored resource. The time since the resource was last scanned (`lastScannedAt`) is compared with the configurable `inspector2_max_days_since_last_scan` threshold (3 days by default).\n\nResources still pending their first scan are not evaluated.", + "Risk": "Stale scans leave **newly published CVEs** and configuration **drift** undetected. A resource that has not been rescanned for weeks can keep running exploitable packages long after a fix is available.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/assessing-coverage.html", + "https://docs.aws.amazon.com/inspector/latest/user/scanning-ecr.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, choose Account management and review the Last scanned at value in the Instances, Container images and Lambda functions tabs\n2. For EC2 instances, confirm the SSM Agent is healthy or, under General settings > EC2 scanning settings, set the scan mode to hybrid\n3. For ECR images, increase the Amazon ECR re-scan duration in the Amazon Inspector settings\n4. Confirm the resources are rescanned", + "Terraform": "" + }, + "Recommendation": { + "Text": "Keep continuous scanning healthy: use **hybrid** EC2 scanning so instances without a working SSM agent are still scanned, set a long ECR **rescan duration** for images in use, and investigate every resource whose last scan is older than the allowed window.", + "Url": "https://hub.prowler.com/check/inspector2_coverage_recently_scanned" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_is_enabled", + "inspector2_coverage_scan_status_active" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py new file mode 100644 index 0000000000..0e5a3bf6fd --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py @@ -0,0 +1,57 @@ +from datetime import datetime, timedelta, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + +PENDING_SCAN_REASONS = { + "PENDING_INITIAL_SCAN", + "PENDING_REVIVAL_SCAN", + "SCAN_IN_PROGRESS", +} + + +class inspector2_coverage_recently_scanned(Check): + """Ensure Inspector2 scanned every actively covered resource within the configured days.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each actively covered resource was scanned within the allowed days.""" + findings = [] + max_days = inspector2_client.audit_config.get( + "inspector2_max_days_since_last_scan", 3 + ) + max_elapsed = timedelta(days=max_days) + now = datetime.now(timezone.utc) + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + if inspector.coverage is None: + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 coverage could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListCoverage permission." + ) + findings.append(report) + continue + for resource in inspector.coverage: + if resource.scan_status_code != "ACTIVE": + continue + if ( + resource.last_scanned_at is None + and resource.scan_status_reason in PENDING_SCAN_REASONS + ): + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=resource) + if resource.last_scanned_at is None: + report.status = "FAIL" + report.status_extended = f"{resource.resource_type} {resource.id} has no recorded Inspector2 scan." + elif now - resource.last_scanned_at > max_elapsed: + report.status = "FAIL" + report.status_extended = f"{resource.resource_type} {resource.id} was last scanned by Inspector2 more than {max_days} days ago." + else: + report.status = "PASS" + report.status_extended = f"{resource.resource_type} {resource.id} was last scanned by Inspector2 within the last {max_days} days." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json new file mode 100644 index 0000000000..0488e5097f --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_coverage_scan_status_active", + "CheckTitle": "Inspector2 covered resource is actively scanned", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** coverage is evaluated for every resource it tracks (EC2 instances, ECR images and repositories, Lambda functions). A resource whose scan status is `INACTIVE`, for example because of `UNMANAGED_EC2_INSTANCE`, `NO_INVENTORY`, `UNSUPPORTED_OS` or `ACCESS_DENIED`, is not being scanned for vulnerabilities.\n\nStopped, terminated, tag-excluded and aged-out resources are not evaluated.", + "Risk": "Resources that Inspector cannot scan silently fall out of **vulnerability detection**. New CVEs affecting those workloads are never reported, so exploitable software can stay deployed while the account still appears covered.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/assessing-coverage.html", + "https://docs.aws.amazon.com/inspector/latest/user/scanning-ec2.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, choose Account management\n2. Open the Instances, Container images or Lambda functions tab and review the resources that are not actively scanned\n3. Fix the reported cause: register EC2 instances with Systems Manager or set the EC2 scan mode to hybrid, use supported operating systems and runtimes, and grant access to the required encryption keys\n4. Confirm the resource is actively scanned", + "Terraform": "" + }, + "Recommendation": { + "Text": "Resolve the reason reported in each inactive resource's scan status so Inspector can scan every in-scope workload. Register EC2 instances with **Systems Manager** or enable **hybrid scanning**, keep operating systems and runtimes supported, and treat scanning gaps as vulnerabilities to track.", + "Url": "https://hub.prowler.com/check/inspector2_coverage_scan_status_active" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_is_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py new file mode 100644 index 0000000000..c1cd63cc02 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py @@ -0,0 +1,46 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + +NOT_APPLICABLE_SCAN_REASONS = { + "EC2_INSTANCE_STOPPED", + "EXCLUDED_BY_TAG", + "NO_RESOURCES_FOUND", + "PENDING_DISABLE", + "RESOURCE_TERMINATED", + "SCAN_ELIGIBILITY_EXPIRED", +} + + +class inspector2_coverage_scan_status_active(Check): + """Ensure Inspector2 is actively scanning every covered resource.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether Inspector2 is actively scanning each covered resource.""" + findings = [] + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + if inspector.coverage is None: + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 coverage could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListCoverage permission." + ) + findings.append(report) + continue + for resource in inspector.coverage: + if resource.scan_status_reason in NOT_APPLICABLE_SCAN_REASONS: + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=resource) + if resource.scan_status_code == "ACTIVE": + report.status = "PASS" + report.status_extended = f"Inspector2 is actively scanning {resource.resource_type} {resource.id}." + else: + report.status = "FAIL" + reason = resource.scan_status_reason or "no reason reported" + report.status_extended = f"Inspector2 is not scanning {resource.resource_type} {resource.id}: {reason}." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_service.py b/prowler/providers/aws/services/inspector2/inspector2_service.py index cc6dac7413..6acf186a66 100644 --- a/prowler/providers/aws/services/inspector2/inspector2_service.py +++ b/prowler/providers/aws/services/inspector2/inspector2_service.py @@ -1,16 +1,33 @@ +from datetime import datetime +from typing import Optional + from pydantic.v1 import BaseModel from prowler.lib.logger import logger +from prowler.lib.scan_filters.scan_filters import is_resource_filtered from prowler.providers.aws.lib.service.service import AWSService +FINDING_DETAILS_BATCH_SIZE = 10 + class Inspector2(AWSService): def __init__(self, provider): # Call AWSService's __init__ super().__init__(__class__.__name__, provider) self.inspectors = [] + self.known_exploited_vulnerabilities = {} + self.vulnerability_lookup_failed = set() self.__threading_call__(self._batch_get_account_status) self.__threading_call__(self._list_active_findings, self.inspectors) + enabled_inspectors = [ + inspector for inspector in self.inspectors if inspector.status == "ENABLED" + ] + self.__threading_call__(self._list_findings, enabled_inspectors) + self.__threading_call__(self._list_coverage, enabled_inspectors) + self.__threading_call__( + self._batch_get_finding_details, + self._get_finding_detail_batches(enabled_inspectors), + ) def _batch_get_account_status(self, regional_client): # We use this function to check if inspector2 is enabled @@ -59,6 +76,188 @@ class Inspector2(AWSService): f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def _list_findings(self, inspector): + """Store the active findings of the audited account for an enabled Region.""" + logger.info("Inspector2 - Listing active findings details...") + try: + paginator = self.regional_clients[inspector.region].get_paginator( + "list_findings" + ) + findings = [] + for page in paginator.paginate( + filterCriteria={ + "awsAccountId": [ + {"comparison": "EQUALS", "value": self.audited_account}, + ], + "findingStatus": [{"comparison": "EQUALS", "value": "ACTIVE"}], + }, + PaginationConfig={"PageSize": 100}, + ): + for finding in page.get("findings", []): + findings.append( + Finding( + arn=finding.get("findingArn", ""), + type=finding.get("type", ""), + severity=finding.get("severity", ""), + first_observed_at=finding.get("firstObservedAt"), + vulnerability_id=finding.get( + "packageVulnerabilityDetails", {} + ).get("vulnerabilityId"), + resource_ids=[ + resource["id"] + for resource in finding.get("resources", []) + if resource.get("id") + ], + ) + ) + inspector.findings = findings + except Exception as error: + logger.error( + f"{inspector.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + def _list_coverage(self, inspector): + """Store the resources Inspector2 covers in an enabled Region, respecting audit resources.""" + logger.info("Inspector2 - Listing coverage...") + try: + paginator = self.regional_clients[inspector.region].get_paginator( + "list_coverage" + ) + coverage = [] + for page in paginator.paginate( + filterCriteria={ + "accountId": [ + {"comparison": "EQUALS", "value": self.audited_account}, + ], + }, + PaginationConfig={"PageSize": 200}, + ): + for covered_resource in page.get("coveredResources", []): + resource_id = covered_resource.get("resourceId", "") + resource_type = covered_resource.get("resourceType", "") + scan_status = covered_resource.get("scanStatus", {}) + arn = self._get_covered_resource_arn( + resource_type, resource_id, inspector.region + ) + if self.audit_resources and not is_resource_filtered( + arn, self.audit_resources + ): + continue + coverage.append( + CoveredResource( + id=resource_id, + arn=arn, + region=inspector.region, + resource_type=resource_type, + scan_type=covered_resource.get("scanType", ""), + scan_status_code=scan_status.get("statusCode", ""), + scan_status_reason=scan_status.get("reason", ""), + last_scanned_at=covered_resource.get("lastScannedAt"), + ) + ) + inspector.coverage = coverage + except Exception as error: + logger.error( + f"{inspector.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + def _get_covered_resource_arn(self, resource_type, resource_id, region): + """Return the ARN of a covered resource, building it for EC2 instance IDs.""" + if resource_type == "AWS_EC2_INSTANCE" and not resource_id.startswith("arn:"): + return f"arn:{self.audited_partition}:ec2:{region}:{self.audited_account}:instance/{resource_id}" + return resource_id + + @staticmethod + def _get_finding_detail_batches(inspectors): + """Group one active finding per CVE into finding details batches per Region.""" + representatives = {} + for inspector in inspectors: + for finding in inspector.findings or []: + if finding.vulnerability_id and finding.vulnerability_id.startswith( + "CVE-" + ): + representatives.setdefault( + finding.vulnerability_id, (inspector.region, finding.arn) + ) + findings_by_region = {} + for vulnerability_id, (region, finding_arn) in representatives.items(): + findings_by_region.setdefault(region, []).append( + (finding_arn, vulnerability_id) + ) + return [ + (region, findings[index : index + FINDING_DETAILS_BATCH_SIZE]) + for region, findings in findings_by_region.items() + for index in range(0, len(findings), FINDING_DETAILS_BATCH_SIZE) + ] + + def _batch_get_finding_details(self, batch): + """Record the CISA KEV data of the CVEs in a batch, flagging failed lookups.""" + region, findings = batch + vulnerability_ids = dict(findings) + logger.info("Inspector2 - Getting finding details...") + try: + response = self.regional_clients[region].batch_get_finding_details( + findingArns=list(vulnerability_ids) + ) + for detail in response.get("findingDetails", []): + vulnerability_id = vulnerability_ids.get(detail.get("findingArn")) + cisa_data = detail.get("cisaData") + if vulnerability_id and cisa_data: + self.known_exploited_vulnerabilities[vulnerability_id] = ( + KnownExploitedVulnerability( + id=vulnerability_id, + date_added=cisa_data.get("dateAdded"), + date_due=cisa_data.get("dateDue"), + ) + ) + for detail_error in response.get("errors", []): + # Inspector has no intelligence for the CVE, so it cannot be a KEV + if detail_error.get("errorCode") == "FINDING_DETAILS_NOT_FOUND": + continue + vulnerability_id = vulnerability_ids.get(detail_error.get("findingArn")) + if vulnerability_id: + self.vulnerability_lookup_failed.add(vulnerability_id) + logger.error( + f"{region} -- {detail_error.get('errorCode')} getting finding details for {vulnerability_id}: {detail_error.get('errorMessage')}" + ) + except Exception as error: + self.vulnerability_lookup_failed.update(vulnerability_ids.values()) + logger.error( + f"{region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + +class Finding(BaseModel): + """Active Inspector2 finding.""" + + arn: str + type: str + severity: str + first_observed_at: Optional[datetime] + vulnerability_id: Optional[str] + resource_ids: list[str] = [] + + +class CoveredResource(BaseModel): + """Resource tracked by Inspector2 coverage.""" + + id: str + arn: str + region: str + resource_type: str + scan_type: str + scan_status_code: str + scan_status_reason: str + last_scanned_at: Optional[datetime] + + +class KnownExploitedVulnerability(BaseModel): + """CISA Known Exploited Vulnerability data of a CVE.""" + + id: str + date_added: Optional[datetime] + date_due: Optional[datetime] + class Inspector(BaseModel): id: str @@ -70,3 +269,5 @@ class Inspector(BaseModel): lambda_status: str lambda_code_status: str active_findings: bool = None + findings: Optional[list[Finding]] = None + coverage: Optional[list[CoveredResource]] = None diff --git a/prowler/providers/aws/services/inspector2/lib/__init__.py b/prowler/providers/aws/services/inspector2/lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py b/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py new file mode 100644 index 0000000000..7544f0de4d --- /dev/null +++ b/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py @@ -0,0 +1,8 @@ +MAX_LISTED_VULNERABILITIES = 10 + + +def summarize_vulnerabilities(vulnerabilities: list[str]) -> str: + """Join vulnerability identifiers, truncating long lists.""" + listed = ", ".join(vulnerabilities[:MAX_LISTED_VULNERABILITIES]) + remaining = len(vulnerabilities) - MAX_LISTED_VULNERABILITIES + return f"{listed} and {remaining} more" if remaining > 0 else listed diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json new file mode 100644 index 0000000000..c1d8b48e20 --- /dev/null +++ b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "transfer_server_fips_security_policy_enabled", + "CheckTitle": "AWS Transfer Family server uses a FIPS security policy", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "transfer", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "low", + "ResourceType": "AwsTransferServer", + "ResourceGroup": "network", + "Description": "**AWS Transfer Family servers** (SFTP, FTPS, AS2) are assessed for use of a **FIPS** security policy (`TransferSecurityPolicy-FIPS-*`, flagged `Fips: true` by AWS), which limits file-transfer sessions to the FIPS-enabled set of SSH and TLS algorithms.", + "Risk": "Servers without a FIPS security policy can negotiate algorithms outside the FIPS-enabled set, which does not meet requirements to protect federal or regulated files and credentials with **NIST CMVP validated cryptography**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/transfer/latest/userguide/security-policies.html", + "https://aws.amazon.com/compliance/fips/" + ], + "Remediation": { + "Code": { + "CLI": "aws transfer update-server --server-id --security-policy-name TransferSecurityPolicy-FIPS-2025-03", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::Transfer::Server\n Properties:\n Protocols:\n - SFTP\n SecurityPolicyName: TransferSecurityPolicy-FIPS-2025-03 # FIX: FIPS security policy\n```", + "Other": "1. In the AWS Console, go to AWS Transfer Family > Servers\n2. Select the server and choose Edit on the Additional details panel\n3. Set Cryptographic algorithm options (Security policy) to a FIPS policy such as TransferSecurityPolicy-FIPS-2025-03\n4. Save the changes", + "Terraform": "```hcl\nresource \"aws_transfer_server\" \"\" {\n protocols = [\"SFTP\"]\n security_policy_name = \"TransferSecurityPolicy-FIPS-2025-03\" # FIX: FIPS security policy\n}\n```" + }, + "Recommendation": { + "Text": "Use a **FIPS** security policy, such as `TransferSecurityPolicy-FIPS-2025-03`, on every Transfer Family server that exchanges federal or regulated data.", + "Url": "https://hub.prowler.com/check/transfer_server_fips_security_policy_enabled" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [ + "transfer_server_in_transit_encryption_enabled", + "transfer_server_pqc_ssh_kex_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py new file mode 100644 index 0000000000..99d86097ba --- /dev/null +++ b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py @@ -0,0 +1,38 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.transfer.transfer_client import transfer_client + + +class transfer_server_fips_security_policy_enabled(Check): + """Ensure every AWS Transfer Family server uses a FIPS security policy.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each Transfer Family server uses a FIPS security policy.""" + findings = [] + unretrieved_servers = [] + for server in transfer_client.servers.values(): + policy = server.security_policy_name + if not policy: + unretrieved_servers.append(server.id) + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=server) + if "FIPS" in policy.split("-"): + report.status = "PASS" + report.status_extended = ( + f"Transfer Server {server.id} uses FIPS security policy {policy}." + ) + else: + report.status = "FAIL" + report.status_extended = f"Transfer Server {server.id} uses security policy {policy}, which is not a FIPS security policy." + findings.append(report) + if unretrieved_servers: + report = Check_Report_AWS(metadata=self.metadata(), resource={}) + report.resource_id = transfer_client.audited_account + report.resource_arn = transfer_client.audited_account_arn + report.region = transfer_client.region + report.status = "MANUAL" + report.status_extended = ( + "Transfer Server security policies could not be retrieved for " + f"{', '.join(unretrieved_servers)}; verify the transfer:DescribeServer permission." + ) + findings.append(report) + return findings diff --git a/tests/config/config_test.py b/tests/config/config_test.py index fbff8ade29..4d469ef009 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -138,6 +138,8 @@ config_aws = { "organizations_enabled_regions": [], "organizations_trusted_delegated_administrators": [], "ecr_repository_vulnerability_minimum_severity": "MEDIUM", + "inspector2_max_days_since_last_scan": 3, + "inspector2_active_finding_max_age_days": 192, "verify_premium_support_plans": True, "threat_detection_privilege_escalation_threshold": 0.2, "threat_detection_privilege_escalation_minutes": 1440, diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index a64e497544..8b02ba2d43 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -139,6 +139,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py b/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py new file mode 100644 index 0000000000..ee1afde340 --- /dev/null +++ b/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py @@ -0,0 +1,156 @@ +from unittest import mock + +from boto3 import client, resource +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_REGION_EU_WEST_1, + AWS_REGION_US_EAST_1, + set_mocked_aws_provider, +) + +CHECK_MODULE = "prowler.providers.aws.services.elbv2.elbv2_listener_fips_tls_enabled.elbv2_listener_fips_tls_enabled" +FIPS_POLICY = "ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04" +NON_FIPS_POLICY = "ELBSecurityPolicy-TLS13-1-2-2021-06" + + +def create_application_load_balancer(): + conn = client("elbv2", region_name=AWS_REGION_EU_WEST_1) + ec2 = resource("ec2", region_name=AWS_REGION_EU_WEST_1) + security_group = ec2.create_security_group( + GroupName="a-security-group", Description="First One" + ) + vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default") + subnet1 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock="172.28.7.192/26", + AvailabilityZone=f"{AWS_REGION_EU_WEST_1}a", + ) + subnet2 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock="172.28.7.0/26", + AvailabilityZone=f"{AWS_REGION_EU_WEST_1}b", + ) + lb = conn.create_load_balancer( + Name="my-lb", + Subnets=[subnet1.id, subnet2.id], + SecurityGroups=[security_group.id], + Scheme="internal", + Type="application", + )["LoadBalancers"][0] + target_group_arn = conn.create_target_group( + Name="a-target", Protocol="HTTP", Port=8080, VpcId=vpc.id + )["TargetGroups"][0]["TargetGroupArn"] + return conn, lb, target_group_arn + + +def create_listener(conn, lb, target_group_arn, protocol, port, ssl_policy=None): + listener_args = { + "LoadBalancerArn": lb["LoadBalancerArn"], + "Protocol": protocol, + "Port": port, + "DefaultActions": [{"Type": "forward", "TargetGroupArn": target_group_arn}], + } + if ssl_policy: + listener_args["SslPolicy"] = ssl_policy + return conn.create_listener(**listener_args)["Listeners"][0] + + +def execute_check(service=None): + from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 + + aws_provider = set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1], + create_default_organization=False, + ) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch(f"{CHECK_MODULE}.elbv2_client", new=service or ELBv2(aws_provider)), + ): + from prowler.providers.aws.services.elbv2.elbv2_listener_fips_tls_enabled.elbv2_listener_fips_tls_enabled import ( + elbv2_listener_fips_tls_enabled, + ) + + return elbv2_listener_fips_tls_enabled().execute() + + +class Test_elbv2_listener_fips_tls_enabled: + @mock_aws + def test_no_load_balancers(self): + assert execute_check() == [] + + @mock_aws + def test_http_listener_only(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTP", 80) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].status_extended == "ELBv2 my-lb has no HTTPS/TLS listeners." + + @mock_aws + def test_fips_policy(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, FIPS_POLICY) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "ELBv2 my-lb has all HTTPS/TLS listeners using a FIPS TLS security policy." + ) + assert result[0].resource_id == "my-lb" + assert result[0].resource_arn == lb["LoadBalancerArn"] + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_non_fips_policy(self): + conn, lb, target_group_arn = create_application_load_balancer() + listener = create_listener( + conn, lb, target_group_arn, "HTTPS", 443, NON_FIPS_POLICY + ) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"ELBv2 my-lb has HTTPS/TLS listeners without a FIPS TLS security policy: HTTPS:443 ({listener['ListenerArn']}) uses {NON_FIPS_POLICY}." + ) + + @mock_aws + def test_mixed_listeners(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, FIPS_POLICY) + create_listener(conn, lb, target_group_arn, "HTTPS", 8443, NON_FIPS_POLICY) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert NON_FIPS_POLICY in result[0].status_extended + assert FIPS_POLICY not in result[0].status_extended + + @mock_aws + def test_listener_discovery_failed(self): + from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 + + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, NON_FIPS_POLICY) + service = ELBv2( + set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1], + create_default_organization=False, + ) + ) + service.loadbalancersv2[lb["LoadBalancerArn"]].listener_discovery_failed = True + + assert execute_check(service) == [] diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py new file mode 100644 index 0000000000..bf57b346c2 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py @@ -0,0 +1,136 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + KnownExploitedVulnerability, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +KEV_ID = "CVE-2024-3400" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_kev_within_due_date.inspector2_active_findings_kev_within_due_date" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(vulnerability_id=KEV_ID): + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="CRITICAL", + first_observed_at=datetime.now(timezone.utc), + vulnerability_id=vulnerability_id, + resource_ids=["i-0123456789abcdef0"], + ) + + +def build_kev(date_due): + return KnownExploitedVulnerability( + id=KEV_ID, + date_added=datetime(2024, 4, 12, tzinfo=timezone.utc), + date_due=date_due, + ) + + +def execute_check(inspectors, known_exploited=None, lookup_failed=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.known_exploited_vulnerabilities = known_exploited or {} + inspector2_client.vulnerability_lookup_failed = lookup_failed or set() + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_kev_within_due_date.inspector2_active_findings_kev_within_due_date import ( + inspector2_active_findings_kev_within_due_date, + ) + + return inspector2_active_findings_kev_within_due_date().execute() + + +class Test_inspector2_active_findings_kev_within_due_date: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_kev_past_due_date(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + known_exploited={ + KEV_ID: build_kev(datetime(2024, 4, 19, tzinfo=timezone.utc)) + }, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities past their remediation due date: {KEV_ID} (due 2024-04-19)." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_kev_within_due_date(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + known_exploited={ + KEV_ID: build_kev(datetime.now(timezone.utc) + timedelta(days=7)) + }, + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities past their remediation due date." + ) + + def test_no_kev_findings(self): + result = execute_check( + [build_inspector(findings=[build_finding("CVE-2022-40897")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_kev_status_not_verified(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + lookup_failed={KEV_ID}, + ) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py new file mode 100644 index 0000000000..288e7224ea --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py @@ -0,0 +1,149 @@ +from datetime import datetime, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + KnownExploitedVulnerability, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +KEV_ID = "CVE-2024-3400" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_no_known_exploited_vulnerabilities.inspector2_active_findings_no_known_exploited_vulnerabilities" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(vulnerability_id): + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="CRITICAL", + first_observed_at=datetime.now(timezone.utc), + vulnerability_id=vulnerability_id, + resource_ids=["i-0123456789abcdef0"], + ) + + +def build_kev(vulnerability_id): + return KnownExploitedVulnerability( + id=vulnerability_id, + date_added=datetime(2024, 4, 12, tzinfo=timezone.utc), + date_due=datetime(2024, 4, 19, tzinfo=timezone.utc), + ) + + +def execute_check(inspectors, known_exploited=None, lookup_failed=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.known_exploited_vulnerabilities = known_exploited or {} + inspector2_client.vulnerability_lookup_failed = lookup_failed or set() + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_no_known_exploited_vulnerabilities.inspector2_active_findings_no_known_exploited_vulnerabilities import ( + inspector2_active_findings_no_known_exploited_vulnerabilities, + ) + + return inspector2_active_findings_no_known_exploited_vulnerabilities().execute() + + +class Test_inspector2_active_findings_no_known_exploited_vulnerabilities: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_no_kev_findings(self): + result = execute_check( + [build_inspector(findings=[build_finding("CVE-2022-40897")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_kev_finding(self): + result = execute_check( + [ + build_inspector( + findings=[build_finding(KEV_ID), build_finding("CVE-2022-40897")] + ) + ], + known_exploited={KEV_ID: build_kev(KEV_ID)}, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities: {KEV_ID}." + ) + + def test_many_kev_findings_are_truncated(self): + vulnerability_ids = [f"CVE-2024-{number:04d}" for number in range(1, 13)] + result = execute_check( + [ + build_inspector( + findings=[build_finding(vid) for vid in vulnerability_ids] + ) + ], + known_exploited={vid: build_kev(vid) for vid in vulnerability_ids}, + ) + + assert result[0].status == "FAIL" + assert result[0].status_extended.endswith("CVE-2024-0010 and 2 more.") + + def test_kev_status_not_verified(self): + result = execute_check( + [build_inspector(findings=[build_finding(KEV_ID)])], + lookup_failed={KEV_ID}, + ) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of {KEV_ID} in region {AWS_REGION_EU_WEST_1}; verify the inspector2:BatchGetFindingDetails permission." + ) + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 findings could not be retrieved in region {AWS_REGION_EU_WEST_1}; verify the inspector2:ListFindings permission." + ) diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py new file mode 100644 index 0000000000..8b847c9014 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py @@ -0,0 +1,140 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_within_max_age.inspector2_active_findings_within_max_age" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(age_days): + first_observed_at = ( + datetime.now(timezone.utc) - timedelta(days=age_days, hours=1) + if age_days is not None + else None + ) + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="HIGH", + first_observed_at=first_observed_at, + vulnerability_id="CVE-2022-40897", + resource_ids=["i-0123456789abcdef0"], + ) + + +def execute_check(inspectors, audit_config=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = audit_config or {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_within_max_age.inspector2_active_findings_within_max_age import ( + inspector2_active_findings_within_max_age, + ) + + return inspector2_active_findings_within_max_age().execute() + + +class Test_inspector2_active_findings_within_max_age: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_no_active_findings(self): + result = execute_check([build_inspector(findings=[])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} first observed more than 192 days ago." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_recent_findings(self): + result = execute_check([build_inspector(findings=[build_finding(30)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_stale_findings(self): + result = execute_check( + [ + build_inspector( + findings=[ + build_finding(30), + build_finding(200), + build_finding(400), + ] + ) + ] + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has 2 active findings in region {AWS_REGION_EU_WEST_1} first observed more than 192 days ago, the oldest 400 days ago." + ) + + def test_finding_just_over_max_age(self): + result = execute_check([build_inspector(findings=[build_finding(192)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_custom_max_age(self): + result = execute_check( + [build_inspector(findings=[build_finding(30)])], + audit_config={"inspector2_active_finding_max_age_days": 14}, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_finding_without_first_observed_date_is_ignored(self): + result = execute_check([build_inspector(findings=[build_finding(None)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" diff --git a/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py b/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py new file mode 100644 index 0000000000..64d757feb2 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py @@ -0,0 +1,170 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + CoveredResource, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +INSTANCE_ID = "i-0123456789abcdef0" +INSTANCE_ARN = ( + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_coverage_recently_scanned.inspector2_coverage_recently_scanned" + + +def build_inspector(coverage=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + coverage=coverage, + ) + + +def build_instance( + days_since_scan=None, scan_status_code="ACTIVE", scan_status_reason="SUCCESSFUL" +): + last_scanned_at = ( + datetime.now(timezone.utc) - timedelta(days=days_since_scan, hours=1) + if days_since_scan is not None + else None + ) + return CoveredResource( + id=INSTANCE_ID, + arn=INSTANCE_ARN, + region=AWS_REGION_EU_WEST_1, + resource_type="AWS_EC2_INSTANCE", + scan_type="PACKAGE", + scan_status_code=scan_status_code, + scan_status_reason=scan_status_reason, + last_scanned_at=last_scanned_at, + ) + + +def execute_check(inspectors, audit_config=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = audit_config or {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_coverage_recently_scanned.inspector2_coverage_recently_scanned import ( + inspector2_coverage_recently_scanned, + ) + + return inspector2_coverage_recently_scanned().execute() + + +class Test_inspector2_coverage_recently_scanned: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(status="DISABLED", coverage=[])]) == [] + + def test_recently_scanned_resource(self): + result = execute_check([build_inspector(coverage=[build_instance(1)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} was last scanned by Inspector2 within the last 3 days." + ) + assert result[0].resource_id == INSTANCE_ID + assert result[0].resource_arn == INSTANCE_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_stale_resource(self): + result = execute_check([build_inspector(coverage=[build_instance(10)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} was last scanned by Inspector2 more than 3 days ago." + ) + + def test_resource_scanned_just_over_max_days(self): + result = execute_check([build_inspector(coverage=[build_instance(3)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_custom_max_days(self): + result = execute_check( + [build_inspector(coverage=[build_instance(10)])], + audit_config={"inspector2_max_days_since_last_scan": 14}, + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_resource_without_recorded_scan(self): + result = execute_check([build_inspector(coverage=[build_instance(None)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} has no recorded Inspector2 scan." + ) + + def test_pending_initial_scan_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[ + build_instance( + None, scan_status_reason="PENDING_INITIAL_SCAN" + ) + ] + ) + ] + ) + == [] + ) + + def test_inactive_resource_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[ + build_instance( + 10, + scan_status_code="INACTIVE", + scan_status_reason="NO_INVENTORY", + ) + ] + ) + ] + ) + == [] + ) + + def test_coverage_not_retrieved(self): + result = execute_check([build_inspector(coverage=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert result[0].resource_arn == INSPECTOR_ARN diff --git a/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py b/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py new file mode 100644 index 0000000000..1ce2e21c4a --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py @@ -0,0 +1,132 @@ +from datetime import datetime, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + CoveredResource, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +INSTANCE_ID = "i-0123456789abcdef0" +INSTANCE_ARN = ( + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_coverage_scan_status_active.inspector2_coverage_scan_status_active" + + +def build_inspector(status="ENABLED", coverage=None): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + coverage=coverage, + ) + + +def build_instance(scan_status_code, scan_status_reason): + return CoveredResource( + id=INSTANCE_ID, + arn=INSTANCE_ARN, + region=AWS_REGION_EU_WEST_1, + resource_type="AWS_EC2_INSTANCE", + scan_type="PACKAGE", + scan_status_code=scan_status_code, + scan_status_reason=scan_status_reason, + last_scanned_at=datetime.now(timezone.utc), + ) + + +def execute_check(inspectors): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_coverage_scan_status_active.inspector2_coverage_scan_status_active import ( + inspector2_coverage_scan_status_active, + ) + + return inspector2_coverage_scan_status_active().execute() + + +class Test_inspector2_coverage_scan_status_active: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(status="DISABLED", coverage=[])]) == [] + + def test_no_covered_resources(self): + assert execute_check([build_inspector(coverage=[])]) == [] + + def test_active_resource(self): + result = execute_check( + [build_inspector(coverage=[build_instance("ACTIVE", "SUCCESSFUL")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 is actively scanning AWS_EC2_INSTANCE {INSTANCE_ID}." + ) + assert result[0].resource_id == INSTANCE_ID + assert result[0].resource_arn == INSTANCE_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_inactive_resource(self): + result = execute_check( + [ + build_inspector( + coverage=[build_instance("INACTIVE", "UNMANAGED_EC2_INSTANCE")] + ) + ] + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 is not scanning AWS_EC2_INSTANCE {INSTANCE_ID}: UNMANAGED_EC2_INSTANCE." + ) + assert result[0].resource_id == INSTANCE_ID + + def test_not_applicable_resource_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[build_instance("INACTIVE", "EC2_INSTANCE_STOPPED")] + ) + ] + ) + == [] + ) + + def test_coverage_not_retrieved(self): + result = execute_check([build_inspector(coverage=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 coverage could not be retrieved in region {AWS_REGION_EU_WEST_1}; verify the inspector2:ListCoverage permission." + ) + assert result[0].resource_arn == INSPECTOR_ARN diff --git a/tests/providers/aws/services/inspector2/inspector2_service_test.py b/tests/providers/aws/services/inspector2/inspector2_service_test.py index c84797eacd..7695e889eb 100644 --- a/tests/providers/aws/services/inspector2/inspector2_service_test.py +++ b/tests/providers/aws/services/inspector2/inspector2_service_test.py @@ -1,18 +1,30 @@ -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import patch import botocore +from botocore.exceptions import ClientError -from prowler.providers.aws.services.inspector2.inspector2_service import Inspector2 +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + Inspector2, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1, + AWS_REGION_US_EAST_1, set_mocked_aws_provider, ) FINDING_ARN = ( "arn:aws:inspector2:us-east-1:123456789012:finding/0e436649379db5f327e3cf5bb4421d76" ) +VULNERABILITY_ID = "CVE-2022-40897" +INSTANCE_ID = "i-0123456789abcdef0" +FIRST_OBSERVED_AT = datetime(2024, 1, 1, tzinfo=timezone.utc) +LAST_SCANNED_AT = datetime(2024, 6, 1, tzinfo=timezone.utc) +KEV_DATE_ADDED = datetime(2024, 4, 12, tzinfo=timezone.utc) +KEV_DATE_DUE = datetime(2024, 5, 3, tzinfo=timezone.utc) # Mocking Calls make_api_call = botocore.client.BaseClient._make_api_call @@ -64,16 +76,83 @@ def mock_make_api_call(self, operation_name, kwargs): "description": "Finding Description", "severity": "MEDIUM", "status": "ACTIVE", - "title": "CVE-2022-40897 - setuptools", + "title": f"{VULNERABILITY_ID} - setuptools", "type": "PACKAGE_VULNERABILITY", + "firstObservedAt": FIRST_OBSERVED_AT, "updatedAt": datetime(2024, 1, 1), + "packageVulnerabilityDetails": { + "vulnerabilityId": VULNERABILITY_ID + }, + "resources": [{"id": INSTANCE_ID, "type": "AWS_EC2_INSTANCE"}], } ] } + if operation_name == "ListCoverage": + return { + "coveredResources": [ + { + "resourceId": INSTANCE_ID, + "resourceType": "AWS_EC2_INSTANCE", + "accountId": AWS_ACCOUNT_NUMBER, + "scanType": "PACKAGE", + "scanStatus": {"statusCode": "ACTIVE", "reason": "SUCCESSFUL"}, + "lastScannedAt": LAST_SCANNED_AT, + } + ] + } + if operation_name == "BatchGetFindingDetails": + return { + "findingDetails": [ + { + "findingArn": FINDING_ARN, + "cisaData": { + "dateAdded": KEV_DATE_ADDED, + "dateDue": KEV_DATE_DUE, + }, + } + ], + "errors": [], + } return make_api_call(self, operation_name, kwargs) +def mock_make_api_call_finding_details_denied(self, operation_name, kwargs): + if operation_name == "BatchGetFindingDetails": + raise ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "denied"}}, + operation_name, + ) + return mock_make_api_call(self, operation_name, kwargs) + + +def mock_finding_details_error(error_code): + def _mock(self, operation_name, kwargs): + if operation_name == "BatchGetFindingDetails": + return { + "findingDetails": [], + "errors": [ + { + "findingArn": FINDING_ARN, + "errorCode": error_code, + "errorMessage": "error", + } + ], + } + return mock_make_api_call(self, operation_name, kwargs) + + return _mock + + +def mock_make_api_call_list_denied(self, operation_name, kwargs): + if operation_name in ("ListFindings", "ListCoverage"): + raise ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "denied"}}, + operation_name, + ) + return mock_make_api_call(self, operation_name, kwargs) + + def mock_generate_regional_clients(provider, service): regional_client = provider._session.current_session.client( service, region_name=AWS_REGION_EU_WEST_1 @@ -82,6 +161,29 @@ def mock_generate_regional_clients(provider, service): return {AWS_REGION_EU_WEST_1: regional_client} +def build_inspector(region, vulnerability_ids): + return Inspector( + id="Inspector2", + arn=f"arn:aws:inspector2:{region}:{AWS_ACCOUNT_NUMBER}:inspector2", + region=region, + status="ENABLED", + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=[ + Finding( + arn=f"arn:aws:inspector2:{region}:{AWS_ACCOUNT_NUMBER}:finding/{index}", + type="PACKAGE_VULNERABILITY", + severity="HIGH", + first_observed_at=FIRST_OBSERVED_AT, + vulnerability_id=vulnerability_id, + ) + for index, vulnerability_id in enumerate(vulnerability_ids) + ], + ) + + # Patch every AWS call using Boto3 and generate_regional_clients to have 1 client @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) @patch( @@ -118,3 +220,115 @@ class Test_Inspector2_Service: aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) inspector2 = Inspector2(aws_provider) assert inspector2.inspectors[0].active_findings + + def test_list_findings(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + findings = inspector2.inspectors[0].findings + assert len(findings) == 1 + assert findings[0].arn == FINDING_ARN + assert findings[0].type == "PACKAGE_VULNERABILITY" + assert findings[0].severity == "MEDIUM" + assert findings[0].first_observed_at == FIRST_OBSERVED_AT + assert findings[0].vulnerability_id == VULNERABILITY_ID + assert findings[0].resource_ids == [INSTANCE_ID] + + def test_list_coverage(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + coverage = inspector2.inspectors[0].coverage + assert len(coverage) == 1 + assert coverage[0].id == INSTANCE_ID + assert ( + coverage[0].arn + == f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" + ) + assert coverage[0].region == AWS_REGION_EU_WEST_1 + assert coverage[0].resource_type == "AWS_EC2_INSTANCE" + assert coverage[0].scan_type == "PACKAGE" + assert coverage[0].scan_status_code == "ACTIVE" + assert coverage[0].scan_status_reason == "SUCCESSFUL" + assert coverage[0].last_scanned_at == LAST_SCANNED_AT + + def test_list_coverage_keeps_audited_resources(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + aws_provider._audit_resources = [ + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" + ] + inspector2 = Inspector2(aws_provider) + assert len(inspector2.inspectors[0].coverage) == 1 + + def test_list_coverage_skips_non_audited_resources(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + aws_provider._audit_resources = [ + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/i-0fedcba9876543210" + ] + inspector2 = Inspector2(aws_provider) + assert inspector2.inspectors[0].coverage == [] + + def test_batch_get_finding_details(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + known_exploited = inspector2.known_exploited_vulnerabilities[VULNERABILITY_ID] + assert known_exploited.id == VULNERABILITY_ID + assert known_exploited.date_added == KEV_DATE_ADDED + assert known_exploited.date_due == KEV_DATE_DUE + assert inspector2.vulnerability_lookup_failed == set() + + def test_batch_get_finding_details_denied(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_make_api_call_finding_details_denied, + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == {VULNERABILITY_ID} + + def test_finding_details_not_found_is_not_a_lookup_failure(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_finding_details_error("FINDING_DETAILS_NOT_FOUND"), + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == set() + + def test_finding_details_error_is_a_lookup_failure(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_finding_details_error("INTERNAL_ERROR"), + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == {VULNERABILITY_ID} + + def test_list_findings_and_coverage_denied(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_make_api_call_list_denied, + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.inspectors[0].findings is None + assert inspector2.inspectors[0].coverage is None + assert inspector2.known_exploited_vulnerabilities == {} + + def test_finding_detail_batches_use_one_finding_per_cve(self): + vulnerability_ids = [f"CVE-2024-{number:04d}" for number in range(25)] + batches = Inspector2._get_finding_detail_batches( + [ + build_inspector( + AWS_REGION_EU_WEST_1, + vulnerability_ids + vulnerability_ids[:5] + ["GHSA-xxxx-yyyy-zzzz"], + ), + build_inspector(AWS_REGION_US_EAST_1, vulnerability_ids[:3]), + ] + ) + assert [region for region, _ in batches] == [AWS_REGION_EU_WEST_1] * 3 + assert [len(findings) for _, findings in batches] == [10, 10, 5] + assert sorted(cve for _, findings in batches for _, cve in findings) == sorted( + vulnerability_ids + ) diff --git a/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py b/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py new file mode 100644 index 0000000000..c60add1918 --- /dev/null +++ b/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py @@ -0,0 +1,111 @@ +from unittest import mock +from unittest.mock import patch + +import botocore +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_US_EAST_1, + set_mocked_aws_provider, +) + +SERVER_ID = "s-01234567890abcdef" +SERVER_ARN = ( + f"arn:aws:transfer:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:server/{SERVER_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.transfer.transfer_server_fips_security_policy_enabled.transfer_server_fips_security_policy_enabled" + +make_api_call = botocore.client.BaseClient._make_api_call + + +def mock_server_with_policy(security_policy_name): + def _mock(self, operation_name, kwarg): + if operation_name == "ListServers": + return {"Servers": [{"Arn": SERVER_ARN, "ServerId": SERVER_ID}]} + if operation_name == "DescribeServer": + return { + "Server": { + "Arn": SERVER_ARN, + "ServerId": SERVER_ID, + "Protocols": ["SFTP"], + "SecurityPolicyName": security_policy_name, + } + } + return make_api_call(self, operation_name, kwarg) + + return _mock + + +def execute_check(): + from prowler.providers.aws.services.transfer.transfer_service import Transfer + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch(f"{CHECK_MODULE}.transfer_client", new=Transfer(aws_provider)), + ): + from prowler.providers.aws.services.transfer.transfer_server_fips_security_policy_enabled.transfer_server_fips_security_policy_enabled import ( + transfer_server_fips_security_policy_enabled, + ) + + return transfer_server_fips_security_policy_enabled().execute() + + +class Test_transfer_server_fips_security_policy_enabled: + @mock_aws + def test_no_servers(self): + assert execute_check() == [] + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy("TransferSecurityPolicy-FIPS-2025-03"), + ) + @mock_aws + def test_fips_policy(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Transfer Server {SERVER_ID} uses FIPS security policy TransferSecurityPolicy-FIPS-2025-03." + ) + assert result[0].resource_id == SERVER_ID + assert result[0].resource_arn == SERVER_ARN + assert result[0].region == AWS_REGION_US_EAST_1 + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy("TransferSecurityPolicy-2024-01"), + ) + @mock_aws + def test_non_fips_policy(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Transfer Server {SERVER_ID} uses security policy TransferSecurityPolicy-2024-01, which is not a FIPS security policy." + ) + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy(""), + ) + @mock_aws + def test_policy_not_retrieved(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Transfer Server security policies could not be retrieved for {SERVER_ID}; verify the transfer:DescribeServer permission." + ) + assert result[0].resource_id == AWS_ACCOUNT_NUMBER + assert result[0].region == AWS_REGION_US_EAST_1