diff --git a/checkov/terraform/graph_builder/foreach/abstract_handler.py b/checkov/terraform/graph_builder/foreach/abstract_handler.py index e83e08338ca..7e684805617 100644 --- a/checkov/terraform/graph_builder/foreach/abstract_handler.py +++ b/checkov/terraform/graph_builder/foreach/abstract_handler.py @@ -131,12 +131,11 @@ def _update_attributes(self, attrs: dict[str, Any], key_to_val_changes: dict[str if attrs[k][0] == dollar_wrapped_str_to_replace: attrs[k][0] = inner_value v_changed = True - break + continue elif dollar_wrapped_str_to_replace in attrs[k][0]: str_to_replace = dollar_wrapped_str_to_replace attrs[k][0] = attrs[k][0].replace(str_to_replace, str(inner_value)) v_changed = True - break else: attrs[k][0] = attrs[k][0].replace("${" + key_to_change + "}", str(val_to_change)) if self.need_to_add_quotes(attrs[k][0], key_to_change): diff --git a/tests/terraform/graph/variable_rendering/test_renderer.py b/tests/terraform/graph/variable_rendering/test_renderer.py index e3bcacf7cb7..f01210c3a0a 100644 --- a/tests/terraform/graph/variable_rendering/test_renderer.py +++ b/tests/terraform/graph/variable_rendering/test_renderer.py @@ -486,3 +486,11 @@ def test_foreach_with_tfvars(self): "role": ["roles/run.developer"], }, ) + + def test_foreach_with_tfvars_tag_merge(self): + resource_path = os.path.join(TEST_DIRNAME, "test_resources", "dynamic_blocks_tfvars_merge") + graph_manager = TerraformGraphManager('m', ['m']) + local_graph, _ = graph_manager.build_graph_from_source_directory(resource_path, render_variables=True) + resources_vertex = list(filter(lambda v: v.block_type == BlockType.RESOURCE, local_graph.vertices)) + self.assertDictEqual(resources_vertex[0].config['aws_instance']['this["vm1"]'].get('tags')[0], + {'Environment': 'prod', 'Department': 'Testing', 'Name': 'vm1'}) diff --git a/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/main.tf b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/main.tf new file mode 100644 index 00000000000..8a926032043 --- /dev/null +++ b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/main.tf @@ -0,0 +1,11 @@ + +resource "aws_instance" "this" { + for_each = { for host in var.vmhosts : host.name => host } + + instance_type = var.instance_type + key_name = var.key_name + private_ip = each.value.private_ip + + tags = merge(each.value.tags, { Name = each.value.name }, {}) + +} diff --git a/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/terraform.tfvars b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/terraform.tfvars new file mode 100644 index 00000000000..98c96cd8654 --- /dev/null +++ b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/terraform.tfvars @@ -0,0 +1,16 @@ + +key_name = "test1" +vmhosts = [ + { + name = "vm1" + tags = { Environment = "prod", Department = "Testing" } + private_ip = "11.101.33.254" + ports = [ 22 ] + }, + { + name = "vm2" + tags = { Environment = "Test" } + private_ip = "22.212.0.200" + ports = [ 80 ] + } +] diff --git a/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/variables.tf b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/variables.tf new file mode 100644 index 00000000000..01e81cfbb0d --- /dev/null +++ b/tests/terraform/graph/variable_rendering/test_resources/dynamic_blocks_tfvars_merge/variables.tf @@ -0,0 +1,17 @@ +variable "instance_type" { + default = "t3.small" +} + +variable "key_name" { + type = string +} + +variable "vmhosts" { + description = "VM hosts with configuration" + type = list(object({ + name = string + tags = map(string) + private_ip = string + ports = list(number) + })) +} \ No newline at end of file