From f5f6b1d71aa4cedc0261c641670a9757ee44fa2b Mon Sep 17 00:00:00 2001 From: ChanochShayner Date: Tue, 17 Oct 2023 15:35:37 +0300 Subject: [PATCH] Support merge inside jsondecode --- .../variable_rendering/evaluate_terraform.py | 11 ++++ .../jsonpath_equals_solver/EcsWithMerge.yaml | 12 +++++ .../jsonpath_equals_solver/test_solver.py | 9 ++++ .../graph/resources/ecs_with_merge/main.tf | 53 +++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/EcsWithMerge.yaml create mode 100644 tests/terraform/graph/resources/ecs_with_merge/main.tf diff --git a/checkov/terraform/graph_builder/variable_rendering/evaluate_terraform.py b/checkov/terraform/graph_builder/variable_rendering/evaluate_terraform.py index 90ccc95f3f6..350ee80d005 100644 --- a/checkov/terraform/graph_builder/variable_rendering/evaluate_terraform.py +++ b/checkov/terraform/graph_builder/variable_rendering/evaluate_terraform.py @@ -67,9 +67,20 @@ def evaluate_terraform(input_str: Any, keep_interpolations: bool = True) -> Any: elif not keep_interpolations and second_evaluated_value == value_after_removing_interpolations: return value_before_removing_interpolations else: + second_evaluated_value = _eval_merge_as_list(second_evaluated_value) return second_evaluated_value +def _eval_merge_as_list(eval_value: Any) -> Any: + """ + Edge case for an eval in eval. + UT for this: test_jsonpath_equals_ecs_with_merge + """ + if eval_value and isinstance(eval_value, list) and isinstance(eval_value[0], str) and eval_value[0].startswith('merge'): + return _try_evaluate(eval_value[0]) + return eval_value + + def _try_evaluate(input_str: Union[str, bool]) -> Any: try: return evaluate(input_str) # type:ignore[arg-type] diff --git a/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/EcsWithMerge.yaml b/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/EcsWithMerge.yaml new file mode 100644 index 00000000000..bfa05a5d8ae --- /dev/null +++ b/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/EcsWithMerge.yaml @@ -0,0 +1,12 @@ + +metadata: + id: "CUSTOM_003" +scope: + provider: "AWS" +definition: + cond_type: "attribute" + resource_types: + - "aws_ecs_task_definition" + attribute: "container_definitions.*.image" + operator: "equals" + value: "service-first" \ No newline at end of file diff --git a/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/test_solver.py b/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/test_solver.py index b3e0f4ce2e0..1219da4cf53 100644 --- a/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/test_solver.py +++ b/tests/terraform/graph/checks_infra/attribute_solvers/jsonpath_equals_solver/test_solver.py @@ -39,3 +39,12 @@ def test_jsonpath_equals_azure_rule(self): expected_results = {check_id: {"should_pass": should_pass, "should_fail": should_fail}} self.run_test(root_folder=root_folder, expected_results=expected_results, check_id=check_id) + + def test_jsonpath_equals_ecs_with_merge(self): + root_folder = '../../../resources/ecs_with_merge' + check_id = "CUSTOM_003" + should_pass = ['aws_ecs_task_definition.service01'] + should_fail = ['aws_ecs_task_definition.service02'] + expected_results = {check_id: {"should_pass": should_pass, "should_fail": should_fail}} + + self.run_test(root_folder=root_folder, expected_results=expected_results, check_id=check_id) diff --git a/tests/terraform/graph/resources/ecs_with_merge/main.tf b/tests/terraform/graph/resources/ecs_with_merge/main.tf new file mode 100644 index 00000000000..431e2f7a2a6 --- /dev/null +++ b/tests/terraform/graph/resources/ecs_with_merge/main.tf @@ -0,0 +1,53 @@ +resource "aws_ecs_task_definition" "service01" { + family = "service" + container_definitions = jsonencode([ + merge( + { + name = "first" + image = "service-first" + }, + { + cpu = 10 + memory = 512 + essential = true + portMappings = [ + { + containerPort = 80 + hostPort = 80 + } + ] + } + ) + ]) + volume { + name = "service-storage" + host_path = "/ecs/service-storage" + } +} + +resource "aws_ecs_task_definition" "service02" { + family = "service" + container_definitions = jsonencode([ + merge( + { + name = "first" + image = "service" + }, + { + cpu = 10 + memory = 512 + essential = true + portMappings = [ + { + containerPort = 80 + hostPort = 80 + } + ] + } + ) + ]) + volume { + name = "service-storage" + host_path = "/ecs/service-storage" + } +} \ No newline at end of file