diff --git a/checkov/common/comment/enum.py b/checkov/common/comment/enum.py index eef4c070ad8..7ef64f8214d 100644 --- a/checkov/common/comment/enum.py +++ b/checkov/common/comment/enum.py @@ -1,3 +1,3 @@ import re -COMMENT_REGEX = re.compile(r'(checkov:skip=|bridgecrew:skip=) *([A-Za-z_\d]+)(:[^\n]+)?') +COMMENT_REGEX = re.compile(r'(checkov:skip=|bridgecrew:skip=) *([A-Za-z_\d]+(?:,[A-Za-z_\d]+)*)?(:[^\n]*)?') diff --git a/checkov/terraform/context_parsers/base_parser.py b/checkov/terraform/context_parsers/base_parser.py index 3d933a9c0d8..c8cccdc056d 100644 --- a/checkov/terraform/context_parsers/base_parser.py +++ b/checkov/terraform/context_parsers/base_parser.py @@ -98,7 +98,7 @@ def _collect_skip_comments(self, definition_blocks: List[Dict[str, Any]]) -> Dic ( line_num, { - "id": match.group(2), + "id": identifier.strip(), "suppress_comment": match.group(3)[1:] if match.group(3) else "No comment provided", }, ) @@ -106,6 +106,7 @@ def _collect_skip_comments(self, definition_blocks: List[Dict[str, Any]]) -> Dic if self.is_optional_comment_line(x) for match in [re.search(COMMENT_REGEX, x)] if match + for identifier in match.group(2).split(",") ] for entity_block in definition_blocks: skipped_checks = [] diff --git a/tests/terraform/context_parsers/mock_tf_files/inline_suppression.tf b/tests/terraform/context_parsers/mock_tf_files/inline_suppression.tf new file mode 100644 index 00000000000..5ee73c38eff --- /dev/null +++ b/tests/terraform/context_parsers/mock_tf_files/inline_suppression.tf @@ -0,0 +1,40 @@ +resource "aws_s3_bucket" "multi-line-multi-checks" { + region = "var.region" + #checkov:skip=CKV_AWS_93,CKV_AWS_21:Skip all + #checkov:skip=CKV_AWS_145:The bucket is a public static content host + bucket = "local.bucket_name" + force_destroy = true + acl = "public-read" +} + +resource "aws_s3_bucket" "multi-line-no-comment" { + region = "var.region" + #checkov:skip=CKV_AWS_93: + #checkov:skip=CKV_AWS_145:The bucket is a public static content host + bucket = "local.bucket_name" + force_destroy = true + acl = "public-read" +} + +resource "aws_s3_bucket" "one-line-one-check" { + region = "var.region" + #checkov:skip=CKV_AWS_145:The bucket is a public static content host + bucket = "local.bucket_name" + force_destroy = true + acl = "public-read" +} + +resource "aws_s3_bucket" "one-line-multi-checks" { + region = "var.region" + #checkov:skip=CKV_AWS_93,CKV_AWS_145:skip all + bucket = "local.bucket_name" + force_destroy = true + acl = "public-read" +} + +resource "aws_s3_bucket" "no-comment" { + region = "var.region" + bucket = "local.bucket_name" + force_destroy = true + acl = "public-read" +} diff --git a/tests/terraform/context_parsers/test_base_parser.py b/tests/terraform/context_parsers/test_base_parser.py index 86e94f9756a..55352285147 100644 --- a/tests/terraform/context_parsers/test_base_parser.py +++ b/tests/terraform/context_parsers/test_base_parser.py @@ -3,12 +3,21 @@ from checkov.common.bridgecrew.integration_features.features.policy_metadata_integration import integration as metadata_integration from checkov.common.bridgecrew.platform_integration import BcPlatformIntegration, bc_integration +from checkov.terraform import TFDefinitionKey +from checkov.terraform.context_parsers.parsers.resource_context_parser import ResourceContextParser from checkov.terraform.context_parsers.registry import parser_registry +from checkov.runner_filter import RunnerFilter +from checkov.terraform.checks.resource.aws.AMICopyUsesCMK import check +from checkov.terraform.runner import Runner +from checkov.terraform.tf_parser import TFParser from tests.terraform.context_parsers.mock_context_parser import MockContextParser mock_tf_file = os.path.dirname(os.path.realpath(__file__)) + "/mock_tf_files/mock.tf" mock_definition = (mock_tf_file, {"mock": [{"mock_type": {"mock_name": {"value": ["mock_value"]}}}]}) +inline_tf_file = os.path.dirname(os.path.realpath(__file__)) + "/mock_tf_files/inline_suppression.tf" +mock_dir_path = os.path.dirname(os.path.realpath(__file__)) + "/mock_tf_files" + class TestBaseParser(unittest.TestCase): def test_enrich_definition_block(self): @@ -46,6 +55,23 @@ def test__compute_definition_end_line_with_multi_curly_brackets(self): # then self.assertEqual(8, end_line_num) + def test_inline_suppression(self): + parser = TFParser() + _, tf_definition = parser.parse_hcl_module(mock_dir_path,source='TERRAFORM') + resources_parser = ResourceContextParser() + parser_registry.register(resources_parser) + inline_key = TFDefinitionKey(inline_tf_file) + inline_suppression_definition = tf_definition[inline_key] + definition_context = parser_registry.enrich_definitions_context((inline_key,inline_suppression_definition)) + + aws_s3_bucket_resources = definition_context[inline_key]["resource"]["aws_s3_bucket"] + + self.assertEqual(len(aws_s3_bucket_resources["multi-line-multi-checks"].get("skipped_checks")), 3) + self.assertEqual(len(aws_s3_bucket_resources["multi-line-no-comment"].get("skipped_checks")), 2) + self.assertEqual(len(aws_s3_bucket_resources["one-line-one-check"].get("skipped_checks")), 1) + self.assertEqual(len(aws_s3_bucket_resources["one-line-multi-checks"].get("skipped_checks")), 2) + self.assertEqual(len(aws_s3_bucket_resources["no-comment"].get("skipped_checks")), 0) + if __name__ == "__main__": unittest.main()