diff --git a/checkov/terraform/graph_builder/foreach/abstract_handler.py b/checkov/terraform/graph_builder/foreach/abstract_handler.py index 8d094a0874a..8a8d9a91182 100644 --- a/checkov/terraform/graph_builder/foreach/abstract_handler.py +++ b/checkov/terraform/graph_builder/foreach/abstract_handler.py @@ -7,7 +7,6 @@ from typing import Any from checkov.common.util.data_structures_utils import pickle_deepcopy -from checkov.terraform import TFModule from checkov.terraform.graph_builder.foreach.consts import COUNT_STRING, FOREACH_STRING, COUNT_KEY, EACH_VALUE, \ EACH_KEY, REFERENCES_VALUES from checkov.terraform.graph_builder.graph_components.block_types import BlockType @@ -67,16 +66,6 @@ def _build_sub_graph(self, blocks_to_render: list[int]) -> TerraformLocalGraph: sub_graph.out_edges = self.local_graph.out_edges return sub_graph - @staticmethod - def _update_nested_tf_module_foreach_idx(original_foreach_or_count_key: int | str, original_module_key: TFModule, - tf_moudle: TFModule | None) -> None: - original_module_key.foreach_idx = None # Make sure it is always None even if we didn't override it previously - while tf_moudle is not None: - if tf_moudle == original_module_key: - tf_moudle.foreach_idx = original_foreach_or_count_key - break - tf_moudle = tf_moudle.nested_tf_module - @staticmethod def _pop_foreach_attrs(attrs: dict[str, Any]) -> None: attrs.pop(COUNT_STRING, None) diff --git a/checkov/terraform/graph_builder/foreach/module_handler.py b/checkov/terraform/graph_builder/foreach/module_handler.py index 135f5776968..caa6fca4845 100644 --- a/checkov/terraform/graph_builder/foreach/module_handler.py +++ b/checkov/terraform/graph_builder/foreach/module_handler.py @@ -7,7 +7,7 @@ from checkov.common.util.consts import RESOLVED_MODULE_ENTRY_NAME from checkov.common.util.data_structures_utils import pickle_deepcopy -from checkov.terraform import TFModule +from checkov.terraform import TFModule, TFDefinitionKey from checkov.terraform.graph_builder.foreach.abstract_handler import ForeachAbstractHandler from checkov.terraform.graph_builder.foreach.consts import FOREACH_STRING, COUNT_STRING from checkov.terraform.graph_builder.graph_components.block_types import BlockType @@ -88,7 +88,7 @@ def _get_current_tf_module_object(self, m_idx: int) -> TFModule: return TFModule(m.path, m_name, m.source_module_object, m.for_each_index) def _create_new_resources_foreach(self, statement: list[str] | dict[str, Any], block_idx: int) -> None: - # Important it will be before the super call to avoid changes occuring from super + # Important it will be before the super call to avoid changes occurring from super main_resource = self.local_graph.vertices[block_idx] super()._create_new_resources_foreach(statement, block_idx) @@ -109,12 +109,9 @@ def _create_new_foreach_resource(self, block_idx: int, foreach_idx: int, main_re def _update_module_children(self, main_resource: TerraformBlock, original_foreach_or_count_key: int | str, should_override_foreach_key: bool = True) -> None: + foreach_idx = original_foreach_or_count_key if not should_override_foreach_key else None original_module_key = TFModule(path=main_resource.path, name=main_resource.name, - nested_tf_module=main_resource.source_module_object) - - if not should_override_foreach_key: - original_module_key.foreach_idx = original_foreach_or_count_key - + nested_tf_module=main_resource.source_module_object, foreach_idx=foreach_idx) self._update_children_foreach_index(original_foreach_or_count_key, original_module_key, should_override_foreach_key=should_override_foreach_key) @@ -137,23 +134,27 @@ def _update_children_foreach_index(self, original_foreach_or_count_key: int | st if current_module_key is None: current_module_key = original_module_key if current_module_key not in self.local_graph.vertices_by_module_dependency: - return + # Make sure we check both the intended key (with foreach key) and the one without the foreach key. + # This is important as we have some iterations in which we try to access with the intended key before + # we actually updated the dict itself + nullified_key = self._get_tf_module_with_no_foreach(current_module_key) + if nullified_key not in self.local_graph.vertices_by_module_dependency: + return + current_module_key = nullified_key values = self.local_graph.vertices_by_module_dependency[current_module_key].values() for child_indexes in values: for child_index in child_indexes: child = self.local_graph.vertices[child_index] - self._update_nested_tf_module_foreach_idx(original_foreach_or_count_key, original_module_key, - child.source_module_object) + child.source_module_object = self._get_module_with_only_relevant_foreach_idx( + original_foreach_or_count_key, original_module_key, child.source_module_object) self._update_resolved_entry_for_tf_definition(child, original_foreach_or_count_key, original_module_key) # Important to copy to avoid changing the object by reference child_source_module_object_copy = pickle_deepcopy(child.source_module_object) if should_override_foreach_key and child_source_module_object_copy is not None: - tf_module: TFModule | None = child_source_module_object_copy - while tf_module is not None: - tf_module.foreach_idx = None - tf_module = tf_module.nested_tf_module + child_source_module_object_copy = self._get_tf_module_with_no_foreach( + child_source_module_object_copy) child_module_key = TFModule(path=child.path, name=child.name, nested_tf_module=child_source_module_object_copy, @@ -162,6 +163,14 @@ def _update_children_foreach_index(self, original_foreach_or_count_key: int | st self._update_children_foreach_index(original_foreach_or_count_key, original_module_key, child_module_key) + @staticmethod + def _get_tf_module_with_no_foreach(original_module: TFModule | None) -> TFModule | None: + if original_module is None: + return original_module + return TFModule(name=original_module.name, path=original_module.path, foreach_idx=None, + nested_tf_module=ForeachModuleHandler._get_tf_module_with_no_foreach( + original_module.nested_tf_module)) + def _create_new_module( self, main_resource: TerraformBlock, @@ -180,7 +189,7 @@ def _create_new_module( main_resource_module_key = TFModule( path=new_resource.path, name=main_resource.name, - nested_tf_module=new_resource.source_module_object, + nested_tf_module=self._get_tf_module_with_no_foreach(new_resource.source_module_object) ) # Without making this copy the test don't pass, as we might access the data structure in the middle of an update @@ -198,8 +207,10 @@ def _create_new_module( else: self.local_graph.vertices[resource_idx] = new_resource - key_with_foreach_index = main_resource_module_key - key_with_foreach_index.foreach_idx = idx_to_change + key_with_foreach_index = TFModule(name=main_resource_module_key.name, + path=main_resource_module_key.path, + nested_tf_module=main_resource_module_key.nested_tf_module, + foreach_idx=idx_to_change) self.local_graph.vertices_by_module_dependency[key_with_foreach_index] = main_resource_module_value self.local_graph.vertices_by_module_dependency_by_name[key_with_foreach_index][new_resource.name] = main_resource_module_value @@ -269,9 +280,28 @@ def _update_resolved_entry_for_tf_definition(child: TerraformBlock, original_for if isinstance(config, dict): resolved_module_name = config.get(RESOLVED_MODULE_ENTRY_NAME) if resolved_module_name is not None and len(resolved_module_name) > 0: - tf_moudle: TFModule = resolved_module_name[0].tf_source_modules - ForeachAbstractHandler._update_nested_tf_module_foreach_idx( + original_definition_key = config[RESOLVED_MODULE_ENTRY_NAME][0] + tf_source_modules = ForeachModuleHandler._get_module_with_only_relevant_foreach_idx( original_foreach_or_count_key, original_module_key, - tf_moudle, + resolved_module_name[0].tf_source_modules, ) + config[RESOLVED_MODULE_ENTRY_NAME][0] = TFDefinitionKey(file_path=original_definition_key.file_path, + tf_source_modules=tf_source_modules) + + @staticmethod + def _get_module_with_only_relevant_foreach_idx(original_foreach_or_count_key: int | str, + original_module_key: TFModule, + tf_moudle: TFModule | None) -> TFModule | None: + if tf_moudle is None: + return None + if tf_moudle == original_module_key: + return TFModule(name=tf_moudle.name, path=tf_moudle.path, + nested_tf_module=tf_moudle.nested_tf_module, + foreach_idx=original_foreach_or_count_key) + nested_module = tf_moudle.nested_tf_module + updated_module = ForeachModuleHandler._get_module_with_only_relevant_foreach_idx( + original_foreach_or_count_key, original_module_key, nested_module) + return TFModule(name=tf_moudle.name, path=tf_moudle.path, + nested_tf_module=updated_module, + foreach_idx=tf_moudle.foreach_idx) diff --git a/checkov/terraform/modules/module_objects.py b/checkov/terraform/modules/module_objects.py index 80fdef5c924..4082709b6c0 100644 --- a/checkov/terraform/modules/module_objects.py +++ b/checkov/terraform/modules/module_objects.py @@ -1,23 +1,16 @@ from __future__ import annotations import json from collections.abc import Iterator -from typing import Optional, Any +from dataclasses import dataclass +from typing import Any +@dataclass(frozen=True) class TFModule: - __slots__ = ("path", "name", "foreach_idx", "nested_tf_module") - - def __init__(self, path: str, name: str | None, nested_tf_module: Optional[TFModule] = None, - foreach_idx: Optional[int | str] = None) -> None: - self.path = path - self.name = name - self.foreach_idx = foreach_idx - self.nested_tf_module = nested_tf_module - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, TFModule): - return False - return self.path == other.path and self.name == other.name and self.nested_tf_module == other.nested_tf_module and self.foreach_idx == other.foreach_idx + path: str + name: str | None + nested_tf_module: TFModule | None = None + foreach_idx: int | str | None = None def __lt__(self, other: Any) -> bool: if not isinstance(other, TFModule): @@ -28,9 +21,6 @@ def __lt__(self, other: Any) -> bool: def __repr__(self) -> str: return f'path:{self.path}, name:{self.name}, nested_tf_module:{self.nested_tf_module}, foreach_idx:{self.foreach_idx}' - def __hash__(self) -> int: - return hash((self.path, self.name, self.nested_tf_module, self.foreach_idx)) - def __iter__(self) -> Iterator[tuple[str, Any]]: yield from { "path": self.path, @@ -50,17 +40,10 @@ def from_json(json_dct: dict[str, Any]) -> TFModule | None: 'nested_tf_module') else None) if json_dct else None +@dataclass(frozen=True) class TFDefinitionKey: - __slots__ = ("tf_source_modules", "file_path") - - def __init__(self, file_path: str, tf_source_modules: Optional[TFModule] = None) -> None: - self.tf_source_modules = tf_source_modules - self.file_path = file_path - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, TFDefinitionKey): - return False - return self.tf_source_modules == other.tf_source_modules and self.file_path == other.file_path + file_path: str + tf_source_modules: TFModule | None = None def __lt__(self, other: Any) -> bool: if not isinstance(other, TFDefinitionKey): @@ -70,9 +53,6 @@ def __lt__(self, other: Any) -> bool: def __repr__(self) -> str: return f'tf_source_modules:{self.tf_source_modules}, file_path:{self.file_path}' - def __hash__(self) -> int: - return hash((self.file_path, self.tf_source_modules)) - def __iter__(self) -> Iterator[tuple[str, Any]]: yield from { "file_path": self.file_path, diff --git a/tests/terraform/graph/variable_rendering/expected_foreach_module_dup_foreach.json b/tests/terraform/graph/variable_rendering/expected_foreach_module_dup_foreach.json new file mode 100644 index 00000000000..e8735ca7d20 --- /dev/null +++ b/tests/terraform/graph/variable_rendering/expected_foreach_module_dup_foreach.json @@ -0,0 +1,1255 @@ +{ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"tf_source_modules\": null}": { + "module": [ + { + "s3_module[\"a\"]": { + "__end_line__": 12, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}" + ], + "__start_line__": 7, + "bucket": [ + false + ], + "bucket2": [ + "" + ], + "source": [ + "./module" + ], + "__address__": "s3_module[\"a\"]" + } + }, + { + "s3_module2[0]": { + "__end_line__": 19, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}" + ], + "__start_line__": 14, + "bucket": [ + "" + ], + "bucket2": [ + true + ], + "source": [ + "./module" + ], + "__address__": "s3_module2[0]" + } + }, + { + "s3_module[\"b\"]": { + "__end_line__": 12, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}" + ], + "__start_line__": 7, + "bucket": [ + false + ], + "bucket2": [ + "" + ], + "source": [ + "./module" + ], + "__address__": "s3_module[\"b\"]" + } + }, + { + "s3_module2[1]": { + "__end_line__": 19, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}" + ], + "__start_line__": 14, + "bucket": [ + "" + ], + "bucket2": [ + true + ], + "source": [ + "./module" + ], + "__address__": "s3_module2[1]" + } + } + ], + "provider": [ + { + "aws": { + "__end_line__": 5, + "__start_line__": 1, + "alias": [ + "test_provider" + ], + "region": [ + "us-west-2" + ], + "test_provider": [ + true + ], + "__address__": "aws.test_provider" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}": { + "module": [ + { + "inner_s3_module[\"c\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"a\"].inner_s3_module[\"c\"]" + } + }, + { + "inner_s3_module2[\"e\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"a\"].inner_s3_module2[\"e\"]" + } + }, + { + "inner_s3_module[\"d\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"a\"].inner_s3_module[\"d\"]" + } + }, + { + "inner_s3_module2[\"f\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"a\"].inner_s3_module2[\"f\"]" + } + } + ], + "variable": [ + { + "bucket": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].bucket" + } + }, + { + "bucket2": { + "__end_line__": 20, + "__start_line__": 18, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}": { + "module": [ + { + "inner_s3_module[\"c\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[0].inner_s3_module[\"c\"]" + } + }, + { + "inner_s3_module2[\"e\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[0].inner_s3_module2[\"e\"]" + } + }, + { + "inner_s3_module[\"d\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[0].inner_s3_module[\"d\"]" + } + }, + { + "inner_s3_module2[\"f\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[0].inner_s3_module2[\"f\"]" + } + } + ], + "variable": [ + { + "bucket": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].bucket" + } + }, + { + "bucket2": { + "__end_line__": 20, + "__start_line__": 18, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"c\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"c\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"c\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"c\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"c\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"c\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"c\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"c\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"e\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"e\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"e\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"e\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"e\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"e\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"e\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"e\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/variable.tf\", \"tf_source_modules\": null}": { + "variable": [ + { + "count_var": { + "__end_line__": 4, + "__start_line__": 2, + "default": [ + 2 + ], + "__address__": "count_var" + } + }, + { + "foreach_var": { + "__end_line__": 8, + "__start_line__": 6, + "default": [ + [ + "a", + "b" + ] + ], + "__address__": "foreach_var" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}": { + "module": [ + { + "inner_s3_module[\"c\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"b\"].inner_s3_module[\"c\"]" + } + }, + { + "inner_s3_module2[\"e\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"b\"].inner_s3_module2[\"e\"]" + } + }, + { + "inner_s3_module[\"d\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"b\"].inner_s3_module[\"d\"]" + } + }, + { + "inner_s3_module2[\"f\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module[\"b\"].inner_s3_module2[\"f\"]" + } + } + ], + "variable": [ + { + "bucket": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].bucket" + } + }, + { + "bucket2": { + "__end_line__": 20, + "__start_line__": 18, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"c\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"c\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"c\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"c\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"e\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"e\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"e\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"e\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}": { + "module": [ + { + "inner_s3_module[\"c\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[1].inner_s3_module[\"c\"]" + } + }, + { + "inner_s3_module2[\"e\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[1].inner_s3_module2[\"e\"]" + } + }, + { + "inner_s3_module[\"d\"]": { + "__end_line__": 5, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 1, + "bucket2": [ + "var.bucket" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[1].inner_s3_module[\"d\"]" + } + }, + { + "inner_s3_module2[\"f\"]": { + "__end_line__": 11, + "__resolved__": [ + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": null, \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}" + ], + "__start_line__": 7, + "bucket2": [ + "var.bucket2" + ], + "source": [ + "./module2" + ], + "__address__": "module.s3_module2[1].inner_s3_module2[\"f\"]" + } + } + ], + "variable": [ + { + "bucket": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].bucket" + } + }, + { + "bucket2": { + "__end_line__": 20, + "__start_line__": 18, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"c\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"c\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"c\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"c\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"e\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"e\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"e\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"e\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"d\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"d\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"d\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module[\"d\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"f\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"a\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"f\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"f\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"a\"].module.inner_s3_module2[\"f\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"d\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"d\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"d\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module[\"d\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"f\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 0, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"f\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"f\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[0].module.inner_s3_module2[\"f\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"d\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"d\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"d\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module[\"d\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"f\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module\", \"foreach_idx\": \"b\", \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"f\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"f\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module[\"b\"].module.inner_s3_module2[\"f\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module\", \"foreach_idx\": \"d\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"d\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"d\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module[\"d\"].bucket2" + } + } + ] + }, + "{\"file_path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/module2/main.tf\", \"tf_source_modules\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/module/main.tf\", \"name\": \"inner_s3_module2\", \"foreach_idx\": \"f\", \"nested_tf_module\": {\"path\": \".../tests/terraform/graph/variable_rendering/resources/foreach_module_dup_foreach/main.tf\", \"name\": \"s3_module2\", \"foreach_idx\": 1, \"nested_tf_module\": null}}}": { + "locals": [ + { + "bucket2": [ + "var.bucket2" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"f\"].bucket2" + } + ], + "resource": [ + { + "aws_s3_bucket_public_access_block": { + "var_bucket": { + "__end_line__": 11, + "__start_line__": 5, + "block_public_acls": [ + true + ], + "block_public_policy": [ + true + ], + "bucket": [ + "var.bucket2" + ], + "ignore_public_acls": [ + true + ], + "restrict_public_buckets": [ + true + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"f\"].aws_s3_bucket_public_access_block.var_bucket" + } + } + } + ], + "variable": [ + { + "bucket2": { + "__end_line__": 16, + "__start_line__": 14, + "type": [ + "string" + ], + "__address__": "module.s3_module2[1].module.inner_s3_module2[\"f\"].bucket2" + } + } + ] + } +} \ No newline at end of file diff --git a/tests/terraform/graph/variable_rendering/test_foreach_renderer.py b/tests/terraform/graph/variable_rendering/test_foreach_renderer.py index b3ce81ffa8c..3bdd01a9140 100644 --- a/tests/terraform/graph/variable_rendering/test_foreach_renderer.py +++ b/tests/terraform/graph/variable_rendering/test_foreach_renderer.py @@ -5,8 +5,10 @@ import pytest from checkov.common.util.json_utils import object_hook, CustomJSONEncoder +from checkov.terraform import TFModule from checkov.terraform.graph_builder.foreach.abstract_handler import ForeachAbstractHandler from checkov.terraform.graph_builder.foreach.builder import ForeachBuilder +from checkov.terraform.graph_builder.foreach.module_handler import ForeachModuleHandler from checkov.terraform.graph_builder.foreach.resource_handler import ForeachResourceHandler from checkov.terraform.graph_builder.graph_to_tf_definitions import convert_graph_vertices_to_tf_definitions @@ -304,18 +306,22 @@ def test_new_tf_parser_with_foreach_modules(checkov_source_path): @mock.patch.dict(os.environ, {"CHECKOV_ENABLE_MODULES_FOREACH_HANDLING": "True"}) def test_tf_definitions_for_foreach_on_modules(checkov_source_path): - dir_name = 'parser_dup_nested' - local_graph, _ = build_and_get_graph_by_path(dir_name, render_var=True) - tf_definitions, _ = convert_graph_vertices_to_tf_definitions(vertices=local_graph.vertices, root_folder=dir_name) + dir_name_and_definitions_path = [ + ('parser_dup_nested', 'expected_foreach_modules_tf_definitions.json'), + ('foreach_module_dup_foreach', 'expected_foreach_module_dup_foreach.json') + ] + for dir_name, definitions_path in dir_name_and_definitions_path: + local_graph, _ = build_and_get_graph_by_path(dir_name, render_var=True) + tf_definitions, _ = convert_graph_vertices_to_tf_definitions(vertices=local_graph.vertices, root_folder=dir_name) - file_path = os.path.join(os.path.dirname(__file__), 'expected_foreach_modules_tf_definitions.json') - with open(file_path, 'r') as f: - expected_data = json.load(f, object_hook=object_hook) + file_path = os.path.join(os.path.dirname(__file__), definitions_path) + with open(file_path, 'r') as f: + expected_data = json.load(f, object_hook=object_hook) - tf_definitions_json = json.dumps(tf_definitions, cls=CustomJSONEncoder) - tf_definitions_json = tf_definitions_json.replace(checkov_source_path, '...') - tf_definitions_after_handling_checkov_source = json.loads(tf_definitions_json, object_hook=object_hook) - assert tf_definitions_after_handling_checkov_source == expected_data + tf_definitions_json = json.dumps(tf_definitions, cls=CustomJSONEncoder) + tf_definitions_json = tf_definitions_json.replace(checkov_source_path, '...') + tf_definitions_after_handling_checkov_source = json.loads(tf_definitions_json, object_hook=object_hook) + assert tf_definitions_after_handling_checkov_source == expected_data @mock.patch.dict(os.environ, {"CHECKOV_ENABLE_MODULES_FOREACH_HANDLING": "True"}) @@ -335,10 +341,29 @@ def test_foreach_module_in_both_levels_module(checkov_source_path): graph, _ = build_and_get_graph_by_path(dir_name, render_var=True) tf_definitions, _ = convert_graph_vertices_to_tf_definitions(vertices=graph.vertices, root_folder=dir_name) - assert len([block for block in graph.vertices if block.block_type == 'module']) == 20 - assert len([block for block in graph.vertices if block.block_type == 'resource']) == 16 + resources = [block for block in graph.vertices if block.block_type == 'resource'] + locals = [block for block in graph.vertices if block.block_type == 'locals'] + vars = [block for block in graph.vertices if block.block_type == 'variable'] + modules = [block for block in graph.vertices if block.block_type == 'module'] + + assert len(modules) == 20 + assert len(resources) == 16 assert len(tf_definitions.keys()) == 22 + for resource in resources: + assert resource.source_module_object.foreach_idx is not None + + for local in locals: + assert local.source_module_object.foreach_idx is not None + + for var in vars: + if var.source_module_object: + assert var.source_module_object.foreach_idx is not None + + for module in modules: + if module.source_module_object: + assert module.source_module_object.foreach_idx is not None + @mock.patch.dict(os.environ, {"CHECKOV_ENABLE_MODULES_FOREACH_HANDLING": "True"}) def test_foreach_module_and_resource(checkov_source_path): @@ -389,3 +414,29 @@ def test_foreach_with_lookup(): graph, _ = build_and_get_graph_by_path(dir_name, render_var=True) assert graph.vertices[0].attributes.get('uniform_bucket_level_access') == [True] assert graph.vertices[1].attributes.get('uniform_bucket_level_access') == [True] + + +def test__get_tf_module_with_no_foreach(): + module = TFModule(name='1', path='1', foreach_idx='1', + nested_tf_module=TFModule(name='2', path='2', foreach_idx='2', nested_tf_module=None)) + result = ForeachModuleHandler._get_tf_module_with_no_foreach(module) + assert result == TFModule(name='1', path='1', foreach_idx=None, + nested_tf_module=TFModule(name='2', path='2', foreach_idx=None, nested_tf_module=None)) + + +def test__get_module_with_only_relevant_foreach_idx(): + module = TFModule(name='1', path='1', foreach_idx='1', + nested_tf_module=TFModule(name='2', path='2', foreach_idx='2', + nested_tf_module=TFModule(name='3', path='3', foreach_idx='3', + nested_tf_module=None) + ) + ) + original_key = TFModule(name='2', path='2', foreach_idx='2', + nested_tf_module=TFModule(name='3', path='3', foreach_idx='3', nested_tf_module=None)) + result = ForeachModuleHandler._get_module_with_only_relevant_foreach_idx('test', original_key, module) + assert result == TFModule(name='1', path='1', foreach_idx='1', + nested_tf_module=TFModule(name='2', path='2', foreach_idx='test', + nested_tf_module=TFModule(name='3', path='3', foreach_idx='3', + nested_tf_module=None) + ) + )