diff --git a/CHANGELOG.md b/CHANGELOG.md index 1aea504d07..f72f723325 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,54 @@ # CHANGELOG -## [Unreleased](https://github.com/bridgecrewio/checkov/compare/3.2.485...HEAD) +## [Unreleased](https://github.com/bridgecrewio/checkov/compare/3.2.493...HEAD) + +## [3.2.493](https://github.com/bridgecrewio/checkov/compare/3.2.492...3.2.493) - 2025-11-12 + +### Feature + +- **general:** support skips for module for_each and count - [#7368](https://github.com/bridgecrewio/checkov/pull/7368) + +## [3.2.492](https://github.com/bridgecrewio/checkov/compare/3.2.491...3.2.492) - 2025-11-10 + +### Bug Fix + +- **terraform:** get_resource_tags handles more cases - [#7365](https://github.com/bridgecrewio/checkov/pull/7365) + +## [3.2.491](https://github.com/bridgecrewio/checkov/compare/3.2.490...3.2.491) - 2025-11-09 + +### Bug Fix + +- **terraform:** Graph report tags should be dict - [#7363](https://github.com/bridgecrewio/checkov/pull/7363) + +## [3.2.490](https://github.com/bridgecrewio/checkov/compare/3.2.489...3.2.490) - 2025-11-04 + +### Feature + +- **general:** Fix downloading of the external modules when ref is a shortened Git hash - [#7278](https://github.com/bridgecrewio/checkov/pull/7278) + +## [3.2.489](https://github.com/bridgecrewio/checkov/compare/3.2.488...3.2.489) - 2025-10-29 + +### Bug Fix + +- **helm:** Check HELM_NAMESPACE env var in CKV_K8S_21 - [#7355](https://github.com/bridgecrewio/checkov/pull/7355) + +## [3.2.488](https://github.com/bridgecrewio/checkov/compare/3.2.487...3.2.488) - 2025-10-27 + +### Feature + +- **terraform_plan:** add new cases for foreach in the presence of skips - [#7351](https://github.com/bridgecrewio/checkov/pull/7351) + +## [3.2.487](https://github.com/bridgecrewio/checkov/compare/3.2.486...3.2.487) - 2025-10-23 + +### Bug Fix + +- **general:** CKV_AWS_174 should-allow-higher-then-TLSv1.2 - terraform and cloudformation - [#7352](https://github.com/bridgecrewio/checkov/pull/7352) + +## [3.2.486](https://github.com/bridgecrewio/checkov/compare/3.2.485...3.2.486) - 2025-10-22 + +### Feature + +- **general:** update setuptools version 78.1.1 - [#7347](https://github.com/bridgecrewio/checkov/pull/7347) ## [3.2.485](https://github.com/bridgecrewio/checkov/compare/3.2.484...3.2.485) - 2025-10-20 diff --git a/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py b/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py index c80f6ffc93..82842f5065 100644 --- a/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py +++ b/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py @@ -1,12 +1,15 @@ -from typing import Any, List +from typing import Any, Dict +import re from checkov.cloudformation.checks.resource.base_resource_value_check import BaseResourceValueCheck -from checkov.common.models.enums import CheckCategories +from checkov.common.models.enums import CheckCategories, CheckResult + +_SECURE_RE = re.compile(r"^TLSv1\.(?:2|3)_\d{4}$") class CloudFrontTLS12(BaseResourceValueCheck): def __init__(self) -> None: - name = "Verify CloudFront Distribution Viewer Certificate is using TLS v1.2" + name = "Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher" id = "CKV_AWS_174" supported_resources = ["AWS::CloudFront::Distribution"] categories = [CheckCategories.ENCRYPTION] @@ -15,11 +18,36 @@ def __init__(self) -> None: def get_inspected_key(self) -> str: return "Properties/DistributionConfig/ViewerCertificate/MinimumProtocolVersion" - def get_expected_values(self) -> List[str]: - return ['TLSv1.2_2018', 'TLSv1.2_2019', 'TLSv1.2_2021'] + @staticmethod + def validate_value(value: Any) -> bool: + return isinstance(value, str) and bool(_SECURE_RE.match(value)) + + def get_evaluated_keys(self): + return [self.get_inspected_key()] + + def scan_resource_conf(self, conf: Dict[str, Any]) -> CheckResult: + # Navigate CFN structure safely + props = conf.get("Properties") + if not isinstance(props, dict): + return CheckResult.FAILED + + dist_cfg = props.get("DistributionConfig") + if not isinstance(dist_cfg, dict): + return CheckResult.FAILED + + viewer_cert = dist_cfg.get("ViewerCertificate") + if not isinstance(viewer_cert, dict): + return CheckResult.FAILED + + # If they use the CloudFront default cert, you can't set a secure policy -> fail explicitly + if viewer_cert.get("CloudFrontDefaultCertificate") is True: + return CheckResult.FAILED + + mpv = viewer_cert.get("MinimumProtocolVersion") + if isinstance(mpv, str) and _SECURE_RE.match(mpv): + return CheckResult.PASSED - def get_expected_value(self) -> Any: - return 'TLSv1.2_2021' + return CheckResult.FAILED check = CloudFrontTLS12() diff --git a/checkov/common/goget/github/get_git.py b/checkov/common/goget/github/get_git.py index 29015d2dbc..0dd2652306 100644 --- a/checkov/common/goget/github/get_git.py +++ b/checkov/common/goget/github/get_git.py @@ -15,7 +15,7 @@ except ImportError as e: git_import_error = e -COMMIT_ID_PATTERN = re.compile(r"\?(ref=)(?P([0-9a-f]{40}))") +COMMIT_ID_PATTERN = re.compile(r"\?(ref=)(?P([0-9a-f]{5,40}))") TAG_PATTERN = re.compile(r'\?(ref=)(?P(.*))') # technically should be with ?ref=tags/ but this catches both BRANCH_PATTERN = re.compile(r'\?(ref=heads/)(?P(.*))') diff --git a/checkov/common/output/report.py b/checkov/common/output/report.py index 3ce4e83d34..51af285332 100644 --- a/checkov/common/output/report.py +++ b/checkov/common/output/report.py @@ -574,6 +574,10 @@ def handle_skipped_checks( if record.resource_address and record.resource_address.startswith("module."): module_path = record.resource_address[module_address_len:record.resource_address.index('.', module_address_len + 1)] + # For module with for_each or count, the module path will be module.module_name[(.*)]. We can + # ignore the index and the for_each value and just use the module name as it's not possible to + # skip checks for a specific instance of a module + module_path = module_path.split('[')[0] module_enrichments = enriched_resources.get(module_path, {}) for module_skip in module_enrichments.get("skipped_checks", []): if record.check_id in module_skip["id"]: @@ -593,10 +597,17 @@ def get_plan_resource_raw_id(resource_id: str) -> str: return the resource raw id without the modules and the indexes example: from resource_id='module.module_name.type.name[1]' return 'type.name' example: from resource_id='type.name['some.long.address']' return 'type.name' + example: from resource_id='module.module_name['some.long.address']'.type.name return 'type.name' + example: from resource_id='module.module_name['some.long.address']'.type.name[1] return 'type.name' """ if '[' in resource_id: - resource_id = resource_id[:resource_id.index('[')] + # remove any information inside brackets + resource_id = resource_id[:resource_id.index('[')] + resource_id[resource_id.index(']') + 1:] + # take last two elements resource_raw_id = ".".join(resource_id.split(".")[-2:]) + if '[' in resource_raw_id: + # cut string at bracket start + resource_raw_id = resource_raw_id[:resource_raw_id.index('[')] return resource_raw_id @classmethod diff --git a/checkov/kubernetes/checks/resource/k8s/DefaultNamespace.py b/checkov/kubernetes/checks/resource/k8s/DefaultNamespace.py index 9f05328542..1583d6540f 100644 --- a/checkov/kubernetes/checks/resource/k8s/DefaultNamespace.py +++ b/checkov/kubernetes/checks/resource/k8s/DefaultNamespace.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os from typing import Any from checkov.common.models.enums import CheckCategories, CheckResult @@ -37,6 +38,8 @@ def scan_spec_conf(self, conf: dict[str, Any]) -> CheckResult: if metadata: if "namespace" in metadata and metadata["namespace"] != "default": return CheckResult.PASSED + if os.getenv('HELM_NAMESPACE') and os.getenv('HELM_NAMESPACE') != "default": + return CheckResult.PASSED # If namespace not defined it is default -> Ignore default Service account and kubernetes service if conf["kind"] == "ServiceAccount" and metadata["name"] == "default": diff --git a/checkov/terraform/base_runner.py b/checkov/terraform/base_runner.py index bdd1bec3a6..c42860b324 100644 --- a/checkov/terraform/base_runner.py +++ b/checkov/terraform/base_runner.py @@ -31,6 +31,7 @@ from checkov.terraform.graph_builder.local_graph import TerraformLocalGraph from checkov.terraform.graph_manager import TerraformGraphManager from checkov.terraform.image_referencer.manager import TerraformImageReferencerManager +from checkov.terraform.tag_providers import get_resource_tags from checkov.terraform.tf_parser import TFParser from checkov.common.util.env_vars_config import env_vars_config @@ -187,7 +188,7 @@ def get_graph_checks_report( entity_context.get("end_line", 1), ], resource=resource, - entity_tags=entity.get("tags", {}), + entity_tags=get_resource_tags(resource, entity_config), evaluations=None, check_class=check.__class__.__module__, file_abs_path=os.path.abspath(full_file_path), diff --git a/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py b/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py index 427139e529..c234c015c6 100644 --- a/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py +++ b/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py @@ -1,25 +1,49 @@ -from typing import List, Any +from typing import Any, Dict +import re -from checkov.common.models.enums import CheckCategories +from checkov.common.models.enums import CheckCategories, CheckResult from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck +_SECURE_RE = re.compile(r"^TLSv1\.(?:2|3)_\d{4}$") + class CloudFrontTLS12(BaseResourceValueCheck): def __init__(self) -> None: - name = "Verify CloudFront Distribution Viewer Certificate is using TLS v1.2" + name = "Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher" id = "CKV_AWS_174" supported_resources = ("aws_cloudfront_distribution",) categories = (CheckCategories.ENCRYPTION,) super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources) def get_inspected_key(self) -> str: + # keep this for reporting return "viewer_certificate/[0]/minimum_protocol_version" - def get_expected_values(self) -> List[Any]: - return ["TLSv1.2_2018", "TLSv1.2_2019", "TLSv1.2_2021"] + def scan_resource_conf(self, conf: Dict[str, Any]) -> CheckResult: + vc_list = conf.get("viewer_certificate") + if not isinstance(vc_list, list) or not vc_list or not isinstance(vc_list[0], dict): + return CheckResult.FAILED + + vc = vc_list[0] + + default_cert = vc.get("cloudfront_default_certificate") + if isinstance(default_cert, list): + default_cert = default_cert[0] if default_cert else None + if isinstance(default_cert, str): + default_cert = default_cert.lower() == "true" + if default_cert is True: + return CheckResult.FAILED + + mpv = vc.get("minimum_protocol_version") + if isinstance(mpv, list): + mpv = mpv[0] if mpv else None + if isinstance(mpv, str) and _SECURE_RE.match(mpv): + return CheckResult.PASSED + + return CheckResult.FAILED - def get_expected_value(self) -> Any: - return "TLSv1.2_2021" + def get_evaluated_keys(self): + return [self.get_inspected_key()] check = CloudFrontTLS12() diff --git a/checkov/terraform/tag_providers/__init__.py b/checkov/terraform/tag_providers/__init__.py index ddbd5b33cb..173240dc4b 100644 --- a/checkov/terraform/tag_providers/__init__.py +++ b/checkov/terraform/tag_providers/__init__.py @@ -4,18 +4,28 @@ from checkov.terraform.tag_providers import azure from checkov.terraform.tag_providers import gcp -provider_tag_mapping = {"aws": aws.get_resource_tags, "azure": azure.get_resource_tags, "gcp": gcp.get_resource_tags} +provider_tag_mapping = {"aws": aws.get_resource_tags, "azure": azure.get_resource_tags, "gcp": gcp.get_resource_tags, + "google": gcp.get_resource_tags} def get_resource_tags(resource_type: str, entity_config: Dict[str, Any]) -> Optional[Dict[str, Any]]: if not isinstance(entity_config, dict): return None - if "_" not in resource_type: - return None # probably not a resource block - provider = resource_type[: resource_type.index("_")] - provider_tag_function = provider_tag_mapping.get(provider) + provider_tag = get_provider_tag(resource_type) + provider_tag_function = provider_tag_mapping.get(provider_tag) if provider_tag else None if provider_tag_function: return provider_tag_function(entity_config) else: return None + + +def get_provider_tag(resource_type: str) -> Optional[str]: + provider_tag = None + if 'aws' in resource_type: + provider_tag = "aws" + elif 'azure' in resource_type: + provider_tag = "azure" + elif 'gcp' in resource_type or 'google' in resource_type: + provider_tag = "gcp" + return provider_tag diff --git a/checkov/version.py b/checkov/version.py index b5e5e78b54..1ade9a5b6c 100644 --- a/checkov/version.py +++ b/checkov/version.py @@ -1 +1 @@ -version = '3.2.486' +version = '3.2.493' diff --git a/docs/5.Policy Index/all.md b/docs/5.Policy Index/all.md index bce4a065b4..83d7a156c8 100644 --- a/docs/5.Policy Index/all.md +++ b/docs/5.Policy Index/all.md @@ -564,8 +564,8 @@ nav_order: 1 | 553 | CKV_AWS_173 | resource | AWS::Lambda::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | | 554 | CKV_AWS_173 | resource | AWS::Serverless::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | | 555 | CKV_AWS_173 | resource | aws_lambda_function | Check encryption settings for Lambda environmental variable | Terraform | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | -| 556 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | -| 557 | CKV_AWS_174 | resource | aws_cloudfront_distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 | Terraform | [CloudfrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py) | +| 556 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | +| 557 | CKV_AWS_174 | resource | aws_cloudfront_distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher | Terraform | [CloudfrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py) | | 558 | CKV_AWS_175 | resource | aws_waf_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | | 559 | CKV_AWS_175 | resource | aws_wafregional_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | | 560 | CKV_AWS_175 | resource | aws_wafv2_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | diff --git a/docs/5.Policy Index/cloudformation.md b/docs/5.Policy Index/cloudformation.md index c8dcf9d149..31a63eed46 100644 --- a/docs/5.Policy Index/cloudformation.md +++ b/docs/5.Policy Index/cloudformation.md @@ -159,7 +159,7 @@ nav_order: 1 | 148 | CKV_AWS_172 | resource | AWS::QLDB::Ledger | Ensure QLDB ledger has deletion protection enabled | Cloudformation | [QLDBLedgerDeletionProtection.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/QLDBLedgerDeletionProtection.py) | | 149 | CKV_AWS_173 | resource | AWS::Lambda::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | | 150 | CKV_AWS_173 | resource | AWS::Serverless::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | -| 151 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | +| 151 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | | 152 | CKV_AWS_187 | resource | AWS::SageMaker::Domain | Ensure Sagemaker domain and notebook instance are encrypted by KMS using a customer managed Key (CMK) | Cloudformation | [SagemakerNotebookEncryptedWithCMK.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/SagemakerNotebookEncryptedWithCMK.py) | | 153 | CKV_AWS_187 | resource | AWS::SageMaker::NotebookInstance | Ensure Sagemaker domain and notebook instance are encrypted by KMS using a customer managed Key (CMK) | Cloudformation | [SagemakerNotebookEncryptedWithCMK.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/SagemakerNotebookEncryptedWithCMK.py) | | 154 | CKV_AWS_192 | resource | AWS::WAFv2::WebACL | Ensure WAF prevents message lookup in Log4j2. See CVE-2021-44228 aka log4jshell | Cloudformation | [WAFACLCVE202144228.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/WAFACLCVE202144228.py) | diff --git a/docs/5.Policy Index/serverless.md b/docs/5.Policy Index/serverless.md index 44b11baab3..d7bb882edf 100644 --- a/docs/5.Policy Index/serverless.md +++ b/docs/5.Policy Index/serverless.md @@ -169,7 +169,7 @@ nav_order: 1 | 148 | CKV_AWS_172 | resource | AWS::QLDB::Ledger | Ensure QLDB ledger has deletion protection enabled | Cloudformation | [QLDBLedgerDeletionProtection.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/QLDBLedgerDeletionProtection.py) | | 149 | CKV_AWS_173 | resource | AWS::Lambda::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | | 150 | CKV_AWS_173 | resource | AWS::Serverless::Function | Check encryption settings for Lambda environment variable | Cloudformation | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | -| 151 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | +| 151 | CKV_AWS_174 | resource | AWS::CloudFront::Distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher | Cloudformation | [CloudFrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/CloudFrontTLS12.py) | | 152 | CKV_AWS_187 | resource | AWS::SageMaker::Domain | Ensure Sagemaker domain and notebook instance are encrypted by KMS using a customer managed Key (CMK) | Cloudformation | [SagemakerNotebookEncryptedWithCMK.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/SagemakerNotebookEncryptedWithCMK.py) | | 153 | CKV_AWS_187 | resource | AWS::SageMaker::NotebookInstance | Ensure Sagemaker domain and notebook instance are encrypted by KMS using a customer managed Key (CMK) | Cloudformation | [SagemakerNotebookEncryptedWithCMK.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/SagemakerNotebookEncryptedWithCMK.py) | | 154 | CKV_AWS_192 | resource | AWS::WAFv2::WebACL | Ensure WAF prevents message lookup in Log4j2. See CVE-2021-44228 aka log4jshell | Cloudformation | [WAFACLCVE202144228.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/cloudformation/checks/resource/aws/WAFACLCVE202144228.py) | diff --git a/docs/5.Policy Index/terraform.md b/docs/5.Policy Index/terraform.md index ab6973b984..3d0b50641c 100644 --- a/docs/5.Policy Index/terraform.md +++ b/docs/5.Policy Index/terraform.md @@ -269,7 +269,7 @@ nav_order: 1 | 258 | CKV_AWS_171 | resource | aws_emr_security_configuration | Ensure EMR Cluster security configuration encryption is using SSE-KMS | Terraform | [EMRClusterIsEncryptedKMS.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/EMRClusterIsEncryptedKMS.py) | | 259 | CKV_AWS_172 | resource | aws_qldb_ledger | Ensure QLDB ledger has deletion protection enabled | Terraform | [QLDBLedgerDeletionProtection.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/QLDBLedgerDeletionProtection.py) | | 260 | CKV_AWS_173 | resource | aws_lambda_function | Check encryption settings for Lambda environmental variable | Terraform | [LambdaEnvironmentEncryptionSettings.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/LambdaEnvironmentEncryptionSettings.py) | -| 261 | CKV_AWS_174 | resource | aws_cloudfront_distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 | Terraform | [CloudfrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py) | +| 261 | CKV_AWS_174 | resource | aws_cloudfront_distribution | Verify CloudFront Distribution Viewer Certificate is using TLS v1.2 or higher | Terraform | [CloudfrontTLS12.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/CloudfrontTLS12.py) | | 262 | CKV_AWS_175 | resource | aws_waf_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | | 263 | CKV_AWS_175 | resource | aws_wafregional_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | | 264 | CKV_AWS_175 | resource | aws_wafv2_web_acl | Ensure WAF has associated rules | Terraform | [WAFHasAnyRules.py](https://github.com/bridgecrewio/checkov/blob/main/checkov/terraform/checks/resource/aws/WAFHasAnyRules.py) | diff --git a/kubernetes/requirements.txt b/kubernetes/requirements.txt index 9baf844b66..d26f47dc23 100644 --- a/kubernetes/requirements.txt +++ b/kubernetes/requirements.txt @@ -1 +1 @@ -checkov==3.2.486 +checkov==3.2.493 diff --git a/tests/cloudformation/checks/resource/aws/example_CloudFrontTLS12/CloudFrontTLS12-PASSED.yaml b/tests/cloudformation/checks/resource/aws/example_CloudFrontTLS12/CloudFrontTLS12-PASSED.yaml index ce7df769ab..9347667662 100644 --- a/tests/cloudformation/checks/resource/aws/example_CloudFrontTLS12/CloudFrontTLS12-PASSED.yaml +++ b/tests/cloudformation/checks/resource/aws/example_CloudFrontTLS12/CloudFrontTLS12-PASSED.yaml @@ -92,4 +92,19 @@ Resources: ViewerCertificate: AcmCertificateArn: "cert-test" MinimumProtocolVersion: TLSv1.2_2021 - SslSupportMethod: sni-only \ No newline at end of file + SslSupportMethod: sni-only + cloudfrontdistributionPASSED4: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + Enabled: true + Origins: + - DomainName: example.com + Id: origin1 + DefaultCacheBehavior: + TargetOriginId: origin1 + ViewerProtocolPolicy: redirect-to-https + ViewerCertificate: + AcmCertificateArn: arn:aws:acm:us-east-1:123456789012:certificate/abc + SslSupportMethod: sni-only + MinimumProtocolVersion: TLSv1.3_2025 \ No newline at end of file diff --git a/tests/cloudformation/checks/resource/aws/test_CloudFrontTLS12.py b/tests/cloudformation/checks/resource/aws/test_CloudFrontTLS12.py index 1c8ee4e0aa..035d61d2c6 100644 --- a/tests/cloudformation/checks/resource/aws/test_CloudFrontTLS12.py +++ b/tests/cloudformation/checks/resource/aws/test_CloudFrontTLS12.py @@ -19,7 +19,8 @@ def test_summary(self): passing_resources = { 'AWS::CloudFront::Distribution.cloudfrontdistributionPASSED1', 'AWS::CloudFront::Distribution.cloudfrontdistributionPASSED2', - 'AWS::CloudFront::Distribution.cloudfrontdistributionPASSED3' + 'AWS::CloudFront::Distribution.cloudfrontdistributionPASSED3', + 'AWS::CloudFront::Distribution.cloudfrontdistributionPASSED4' } failing_resources = { @@ -31,7 +32,7 @@ def test_summary(self): passed_check_resources = set([c.resource for c in report.passed_checks]) failed_check_resources = set([c.resource for c in report.failed_checks]) - self.assertEqual(summary['passed'], 3) + self.assertEqual(summary['passed'], 4) self.assertEqual(summary['failed'], 3) self.assertEqual(summary['skipped'], 0) self.assertEqual(summary['parsing_errors'], 0) diff --git a/tests/common/goget/test_goget_github.py b/tests/common/goget/test_goget_github.py index 3b63e41195..8930483b5c 100644 --- a/tests/common/goget/test_goget_github.py +++ b/tests/common/goget/test_goget_github.py @@ -108,6 +108,17 @@ def test_parse_commit_id(self): self.assertEqual("aa218f56b14c9653891f9e74264a383fa43fefbd", getter.commit_id, "Parsed source commit_id is wrong") + def test_parse_shortened_commit_id(self): + """Test parsing of shortened git commit IDs (5-39 characters).""" + url = "https://my-git.com/owner/repository-name?ref=aa218" + getter = GitGetter(url) + git_url = getter.extract_git_ref(url) + + self.assertEqual( + "https://my-git.com/owner/repository-name", git_url, "Parsed source url is wrong for 5-char commit" + ) + self.assertEqual("aa218", getter.commit_id, "Parsed source commit_id is wrong for 5-char commit") + @patch('checkov.common.goget.github.get_git.Repo') @patch('shutil.copytree') @patch('os.makedirs') diff --git a/tests/common/output/test_report.py b/tests/common/output/test_report.py index d98cf20b7d..33059dc74c 100644 --- a/tests/common/output/test_report.py +++ b/tests/common/output/test_report.py @@ -46,4 +46,39 @@ def test_from_reduced_json(json_reduced_report): " runs-on: ubuntu-latest\n" ], ] - assert passed_check.bc_check_id == 'BC_REPO_GITHUB_ACTION_1' \ No newline at end of file + assert passed_check.bc_check_id == 'BC_REPO_GITHUB_ACTION_1' + + +def test_get_plan_resource_raw_id_1(): + resource_id = Report.get_plan_resource_raw_id("module.vnet[0].azurerm_subnet.subnet_for_each['snet-commonservices']") + assert resource_id == 'azurerm_subnet.subnet_for_each' + + +def test_get_plan_resource_raw_id_2(): + resource_id = Report.get_plan_resource_raw_id("module.vnet[0].azurerm_subnet.subnet_for_each[1]") + assert resource_id == 'azurerm_subnet.subnet_for_each' + + +def test_get_plan_resource_raw_id_3(): + resource_id = Report.get_plan_resource_raw_id("module.vnet[0].azurerm_subnet.subnet_for_each") + assert resource_id == 'azurerm_subnet.subnet_for_each' + + +def test_get_plan_resource_raw_id_4(): + resource_id = Report.get_plan_resource_raw_id("module.vnet.azurerm_subnet.subnet_for_each") + assert resource_id == 'azurerm_subnet.subnet_for_each' + + +def test_get_plan_resource_raw_id_5(): + resource_id = Report.get_plan_resource_raw_id("aws_route53_zone.example[\"example.com\"]") + assert resource_id == 'aws_route53_zone.example' + + +def test_get_plan_resource_raw_id_6(): + resource_id = Report.get_plan_resource_raw_id("module.sg[\"bad_example\"].aws_security_group.bad") + assert resource_id == 'aws_security_group.bad' + + +def test_get_plan_resource_raw_id_7(): + resource_id = Report.get_plan_resource_raw_id("type.name") + assert resource_id == 'type.name' diff --git a/tests/common/runner_registry/plan_with_for_each_for_enrichment/original/main.tf b/tests/common/runner_registry/plan_with_for_each_for_enrichment/original/main.tf index 0326bafdc4..da87b9fd91 100644 --- a/tests/common/runner_registry/plan_with_for_each_for_enrichment/original/main.tf +++ b/tests/common/runner_registry/plan_with_for_each_for_enrichment/original/main.tf @@ -9,4 +9,16 @@ resource "aws_route53_zone" "example" { for_each = toset(local.hosted_zone_names) # checkov:skip=CKV2_AWS_38 name = each.value +} + +locals { + names = ["bad_example", "terrible_example", "awful_example"] +} + +module "sg" { + # checkov:skip=CKV_AWS_277 + for_each = toset(local.names) + name = each.value + source = "./modules/ec2/security_group" + vpc_id = var.vpc_id } \ No newline at end of file diff --git a/tests/common/runner_registry/plan_with_for_each_for_enrichment/tf_plan.json b/tests/common/runner_registry/plan_with_for_each_for_enrichment/tf_plan.json index 4aed738a61..66cf914e4d 100644 --- a/tests/common/runner_registry/plan_with_for_each_for_enrichment/tf_plan.json +++ b/tests/common/runner_registry/plan_with_for_each_for_enrichment/tf_plan.json @@ -1,11 +1,11 @@ { "format_version": "1.2", - "terraform_version": "1.5.7", + "terraform_version": "1.9.5", "planned_values": { "root_module": { "resources": [ { - "address": "aws_route53_zone.example['example.com']", + "address": "aws_route53_zone.example[\"example.com\"]", "mode": "managed", "type": "aws_route53_zone", "name": "example", @@ -27,7 +27,7 @@ } }, { - "address": "aws_route53_zone.example['example2.eu']", + "address": "aws_route53_zone.example[\"example2.eu\"]", "mode": "managed", "type": "aws_route53_zone", "name": "example", @@ -44,12 +44,764 @@ }, "sensitive_values": { "name_servers": [], - "tags_all": { - }, + "tags_all": {}, "vpc": [] } } + ], + "child_modules": [ + { + "resources": [ + { + "address": "module.sg[\"awful_example\"].aws_security_group.bad", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "awful_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "sensitive_values": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + ], + "address": "module.sg[\"awful_example\"]" + }, + { + "resources": [ + { + "address": "module.sg[\"bad_example\"].aws_security_group.bad", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "bad_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "sensitive_values": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + ], + "address": "module.sg[\"bad_example\"]" + }, + { + "resources": [ + { + "address": "module.sg[\"terrible_example\"].aws_security_group.bad", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "terrible_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "sensitive_values": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + ], + "address": "module.sg[\"terrible_example\"]" + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_route53_zone.example[\"example.com\"]", + "mode": "managed", + "type": "aws_route53_zone", + "name": "example", + "index": "example.com", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "comment": "Managed by Terraform", + "delegation_set_id": null, + "force_destroy": false, + "name": "example.com", + "tags": null, + "vpc": [] + }, + "after_unknown": { + "arn": true, + "id": true, + "name_servers": true, + "primary_name_server": true, + "tags_all": true, + "vpc": [], + "zone_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "name_servers": [], + "tags_all": {}, + "vpc": [] + } + } + }, + { + "address": "aws_route53_zone.example[\"example2.eu\"]", + "mode": "managed", + "type": "aws_route53_zone", + "name": "example", + "index": "example2.eu", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "comment": "Managed by Terraform", + "delegation_set_id": null, + "force_destroy": false, + "name": "example2.eu", + "tags": null, + "vpc": [] + }, + "after_unknown": { + "arn": true, + "id": true, + "name_servers": true, + "primary_name_server": true, + "tags_all": true, + "vpc": [], + "zone_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "name_servers": [], + "tags_all": {}, + "vpc": [] + } + } + }, + { + "address": "module.sg[\"awful_example\"].aws_security_group.bad", + "module_address": "module.sg[\"awful_example\"]", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "awful_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "after_unknown": { + "arn": true, + "egress": true, + "id": true, + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "name_prefix": true, + "owner_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + }, + { + "address": "module.sg[\"bad_example\"].aws_security_group.bad", + "module_address": "module.sg[\"bad_example\"]", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "bad_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "after_unknown": { + "arn": true, + "egress": true, + "id": true, + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "name_prefix": true, + "owner_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + }, + { + "address": "module.sg[\"terrible_example\"].aws_security_group.bad", + "module_address": "module.sg[\"terrible_example\"]", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "Managed by Terraform", + "ingress": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "protocol": "-1", + "security_groups": [], + "self": false, + "to_port": 65535 + } + ], + "name": "terrible_example", + "revoke_rules_on_delete": false, + "tags": null, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "after_unknown": { + "arn": true, + "egress": true, + "id": true, + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "name_prefix": true, + "owner_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "egress": [], + "ingress": [ + { + "cidr_blocks": [ + false + ], + "ipv6_cidr_blocks": [], + "prefix_list_ids": [], + "security_groups": [] + } + ], + "tags_all": {} + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.9.5", + "values": { + "root_module": { + "resources": [ + { + "address": "data.aws_subnet.private", + "mode": "data", + "type": "aws_subnet", + "name": "private", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:ec2:us-east-1:073481610293:subnet/subnet-04c460d388900659b", + "assign_ipv6_address_on_creation": false, + "availability_zone": "us-east-1c", + "availability_zone_id": "use1-az1", + "available_ip_address_count": 248, + "cidr_block": "10.213.220.0/24", + "customer_owned_ipv4_pool": "", + "default_for_az": false, + "enable_dns64": false, + "enable_lni_at_device_index": 0, + "enable_resource_name_dns_a_record_on_launch": false, + "enable_resource_name_dns_aaaa_record_on_launch": false, + "filter": [ + { + "name": "tag:Name", + "values": [ + "dev-vpc" + ] + } + ], + "id": "subnet-04c460d388900659b", + "ipv6_cidr_block": "", + "ipv6_cidr_block_association_id": "", + "ipv6_native": false, + "map_customer_owned_ip_on_launch": false, + "map_public_ip_on_launch": false, + "outpost_arn": "", + "owner_id": "073481610293", + "private_dns_hostname_type_on_launch": "ip-name", + "state": "available", + "tags": { + "Name": "dev-vpc", + "karpenter.sh/discovery": "true", + "kubernetes.io/role/internal-elb": "1" + }, + "timeouts": null, + "vpc_id": "vpc-123456abc" + }, + "sensitive_values": { + "filter": [ + { + "values": [ + false + ] + } + ], + "tags": {} + } + }, + { + "address": "data.aws_vpc.sandbox", + "mode": "data", + "type": "aws_vpc", + "name": "sandbox", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:ec2:us-east-1:073481610293:vpc/vpc-123456abc", + "cidr_block": "10.213.220.0/22", + "cidr_block_associations": [ + { + "association_id": "vpc-cidr", + "cidr_block": "10.213.220.0/22", + "state": "associated" + } + ], + "default": false, + "dhcp_options_id": "dopt-123456abc", + "enable_dns_hostnames": true, + "enable_dns_support": true, + "enable_network_address_usage_metrics": true, + "filter": [ + { + "name": "tag:Name", + "values": [ + "dev-vpc" + ] + } + ], + "id": "vpc-123456abc", + "instance_tenancy": "default", + "ipv6_association_id": "", + "ipv6_cidr_block": "", + "main_route_table_id": "", + "owner_id": "073481610293", + "state": null, + "timeouts": null + }, + "sensitive_values": { + "cidr_block_associations": [ + {} + ], + "filter": [ + { + "values": [ + false + ] + } + ], + "tags": {} + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_route53_zone.example", + "mode": "managed", + "type": "aws_route53_zone", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "name": { + "references": [ + "each.value" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "local.hosted_zone_names" + ] + } + }, + { + "address": "data.aws_subnet.private", + "mode": "data", + "type": "aws_subnet", + "name": "private", + "provider_config_key": "aws", + "expressions": { + "filter": [ + { + "name": { + "constant_value": "tag:Name" + }, + "values": { + "constant_value": [ + "dev-vpc" + ] + } + } + ], + "vpc_id": { + "references": [ + "data.aws_vpc.sandbox.id", + "data.aws_vpc.sandbox" + ] + } + }, + "schema_version": 0 + }, + { + "address": "data.aws_vpc.sandbox", + "mode": "data", + "type": "aws_vpc", + "name": "sandbox", + "provider_config_key": "aws", + "expressions": { + "filter": [ + { + "name": { + "constant_value": "tag:Name" + }, + "values": { + "constant_value": [ + "dev-vpc" + ] + } + } + ] + }, + "schema_version": 0 + } + ], + "module_calls": { + "sg": { + "source": "./modules/ec2/security_group", + "expressions": { + "name": { + "references": [ + "each.value" + ] + }, + "vpc_id": { + "references": [ + "data.aws_vpc.sandbox.id", + "data.aws_vpc.sandbox" + ] + } + }, + "for_each_expression": { + "references": [ + "local.names" + ] + }, + "module": { + "outputs": { + "aws_security_group_id": { + "expression": { + "references": [ + "aws_security_group.bad.id", + "aws_security_group.bad" + ] + }, + "description": "The ID of the security group" + } + }, + "resources": [ + { + "address": "aws_security_group.bad", + "mode": "managed", + "type": "aws_security_group", + "name": "bad", + "provider_config_key": "aws", + "expressions": { + "ingress": { + "constant_value": [ + { + "cidr_blocks": [ + "0.0.0.0/0" + ], + "description": "Allow all inbound traffic", + "from_port": 0, + "ipv6_cidr_blocks": null, + "prefix_list_ids": null, + "protocol": "-1", + "security_groups": null, + "self": null, + "to_port": 65535 + } + ] + }, + "name": { + "references": [ + "var.name" + ] + }, + "vpc_id": { + "references": [ + "var.vpc_id" + ] + } + }, + "schema_version": 1 + } + ], + "variables": { + "name": { + "description": "The name of the security group" + }, + "vpc_id": { + "description": "The VPC ID to associate with the security group" + } + } + } + } + } + } + }, + "relevant_attributes": [ + { + "resource": "module.sg[\"awful_example\"].aws_security_group.bad", + "attribute": [ + "id" + ] + }, + { + "resource": "module.sg[\"terrible_example\"].aws_security_group.bad", + "attribute": [ + "id" + ] + }, + { + "resource": "module.sg[\"bad_example\"].aws_security_group.bad", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_vpc.sandbox", + "attribute": [ + "id" ] } - } -} + ], + "timestamp": "2025-10-21T13:18:15Z", + "applyable": true, + "complete": true, + "errored": false +} \ No newline at end of file diff --git a/tests/common/runner_registry/test_runner_registry_plan_enrichment.py b/tests/common/runner_registry/test_runner_registry_plan_enrichment.py index 5044a745cd..84cdfecf7f 100644 --- a/tests/common/runner_registry/test_runner_registry_plan_enrichment.py +++ b/tests/common/runner_registry/test_runner_registry_plan_enrichment.py @@ -122,7 +122,7 @@ def test_enrichment_of_plan_report_with_modules(self): self.assertEqual(enriched_data, expected_enriched_data) def test_enrichment_of_plan_report_with_for_each(self): - allowed_checks = ["CKV2_AWS_38"] + allowed_checks = ["CKV2_AWS_38", "CKV_AWS_277"] runner_registry = RunnerRegistry( banner, RunnerFilter(checks=allowed_checks, framework=["terraform_plan"]), tf_plan_runner() ) @@ -136,7 +136,7 @@ def test_enrichment_of_plan_report_with_for_each(self): self.assertEqual(len(report.passed_checks), 0) - self.assertEqual(len(report.skipped_checks), 2) + self.assertEqual(len(report.skipped_checks), 5) def test_skip_check(self): @@ -158,6 +158,7 @@ def test_skip_check(self): self.assertEqual(len(skipped_check_ids), 2) self.assertEqual(skipped_check_ids, expected_skipped_check_ids) + def test_skip_check_in_module(self): allowed_checks = ["CKV_AWS_19", "CKV2_AWS_6"] runner_registry = RunnerRegistry( diff --git a/tests/kubernetes/checks/test_DefaultNamespace.py b/tests/kubernetes/checks/test_DefaultNamespace.py index 1f5788c253..8b64a4c78b 100644 --- a/tests/kubernetes/checks/test_DefaultNamespace.py +++ b/tests/kubernetes/checks/test_DefaultNamespace.py @@ -1,5 +1,6 @@ import os import unittest +from unittest import mock from checkov.kubernetes.checks.resource.k8s.DefaultNamespace import check from checkov.kubernetes.runner import Runner @@ -21,6 +22,19 @@ def test_summary(self): self.assertEqual(summary['skipped'], 0) self.assertEqual(summary['parsing_errors'], 0) + @mock.patch.dict(os.environ, {"HELM_NAMESPACE": "non-default"}) + def test_summary_with_env_var(self): + runner = Runner() + current_dir = os.path.dirname(os.path.realpath(__file__)) + test_files_dir = current_dir + "/example_DefaultNamespace" + report = runner.run(root_folder=test_files_dir, runner_filter=RunnerFilter(checks=[check.id])) + summary = report.get_summary() + + self.assertEqual(summary['passed'], 11) + self.assertEqual(summary['failed'], 0) + self.assertEqual(summary['skipped'], 0) + self.assertEqual(summary['parsing_errors'], 0) + if __name__ == '__main__': unittest.main() diff --git a/tests/terraform/checks/resource/aws/example_CloudfrontTLS12/main.tf b/tests/terraform/checks/resource/aws/example_CloudfrontTLS12/main.tf index 77f6c2cd92..97b61e6477 100644 --- a/tests/terraform/checks/resource/aws/example_CloudfrontTLS12/main.tf +++ b/tests/terraform/checks/resource/aws/example_CloudfrontTLS12/main.tf @@ -528,3 +528,44 @@ resource "aws_cloudfront_distribution" "pass1" { minimum_protocol_version = "TLSv1.2_2019" } } + +resource "aws_cloudfront_distribution" "pass2" { + origin { + domain_name = aws_s3_bucket.b.bucket_regional_domain_name + origin_id = local.s3_origin_id + + s3_origin_config { + origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567" + } + } + + enabled = true + is_ipv6_enabled = true + default_root_object = "index.html" + + default_cache_behavior { + allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + target_origin_id = local.s3_origin_id + viewer_protocol_policy = "redirect-to-https" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + } + + price_class = "PriceClass_200" + + restrictions { + geo_restriction { + restriction_type = "whitelist" + locations = ["US", "CA", "GB", "DE"] + } + } + + viewer_certificate { + acm_certificate_arn = aws_acm_certificate.cert.arn + ssl_support_method = "sni-only" + minimum_protocol_version = "TLSv1.3_2025" + } +} + diff --git a/tests/terraform/checks/resource/aws/test_CloudFrontTLS12.py b/tests/terraform/checks/resource/aws/test_CloudFrontTLS12.py index 1065d79f2c..f0464f5485 100644 --- a/tests/terraform/checks/resource/aws/test_CloudFrontTLS12.py +++ b/tests/terraform/checks/resource/aws/test_CloudFrontTLS12.py @@ -18,6 +18,7 @@ def test(self): passing_resources = { "aws_cloudfront_distribution.pass", "aws_cloudfront_distribution.pass1", + "aws_cloudfront_distribution.pass2", } failing_resources = { "aws_cloudfront_distribution.fail", @@ -28,7 +29,7 @@ def test(self): passed_check_resources = set([c.resource for c in report.passed_checks]) failed_check_resources = set([c.resource for c in report.failed_checks]) - self.assertEqual(summary["passed"], 2) + self.assertEqual(summary["passed"], 3) self.assertEqual(summary["failed"], 3) self.assertEqual(summary["skipped"], 0) self.assertEqual(summary["parsing_errors"], 0) diff --git a/tests/terraform/test_provider_tags.py b/tests/terraform/test_provider_tags.py new file mode 100644 index 0000000000..84f989cb71 --- /dev/null +++ b/tests/terraform/test_provider_tags.py @@ -0,0 +1,13 @@ +import pytest + +from checkov.terraform.tag_providers import get_provider_tag + + +@pytest.mark.parametrize("resource_type, expected", [ + ("aws_instance.example", "aws"), + ("module.test.aws_instance.example", "aws"), + ("azure_instance.example", "azure"), + ("google_instance.example", "gcp"), +]) +def test_get_provider_tag(resource_type, expected) -> None: + assert get_provider_tag(resource_type) == expected