From 55163c4cce7a4320cdbe826ba6e39f421ad60a8f Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 07:27:40 +0000 Subject: [PATCH 1/8] adding module cross reference check --- modules/graphmaker.py | 117 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/modules/graphmaker.py b/modules/graphmaker.py index 511ce7d..8bf585a 100644 --- a/modules/graphmaker.py +++ b/modules/graphmaker.py @@ -230,6 +230,113 @@ def check_relationship( return connection_pairs +def scan_module_relationships( + tfdata: Dict[str, Any], graphdict: Dict[str, List[str]] +) -> None: + """Scan module-to-module relationships via output references and direct resource references.""" + if not tfdata.get("all_module"): + return + + # Get provider prefixes for multi-cloud support + config = _get_provider_config(tfdata) + provider_prefixes = config.PROVIDER_PREFIX # e.g., ["aws_", "google_", "azurerm_"] + + # Build regex pattern for any provider resource (e.g., aws_|google_|azurerm_) + provider_pattern = "|".join([p.replace("_", "\_") for p in provider_prefixes]) + direct_ref_pattern = rf"module\.(\w+)\.({provider_pattern}\w+)\.(\w+)" + + for filepath, module_list in tfdata["all_module"].items(): + if not isinstance(module_list, list): + continue + for module_dict in module_list: + if not isinstance(module_dict, dict): + continue + for module_name, module_metadata in module_dict.items(): + if not isinstance(module_metadata, dict): + continue + + # Find resources in this module + module_resources = [ + n + for n in tfdata["node_list"] + if n.startswith(f"module.{module_name}.") + ] + if not module_resources: + continue + + metadata_str = str(module_metadata) + + # Find direct resource references (e.g., module.s3_bucket.aws_s3_bucket.this) + direct_refs = re.findall(direct_ref_pattern, metadata_str) + for ref_module_name, resource_type, resource_name in set(direct_refs): + if ref_module_name == module_name: + continue + # Find matching resources in node_list + target_pattern = ( + f"module.{ref_module_name}.{resource_type}.{resource_name}" + ) + target_resources = [ + n for n in tfdata["node_list"] if target_pattern in n + ] + # Create connections + for origin in module_resources: + for dest in target_resources: + if origin in graphdict and dest not in graphdict[origin]: + add_connection(graphdict, origin, dest) + + # Find module output references (e.g., module.s3_bucket.bucket_id) + module_output_refs = re.findall(r"module\.(\w+)\.(\w+)", metadata_str) + for ref_module_name, output_name in set(module_output_refs): + if ref_module_name == module_name: + continue + # Skip if already handled as direct reference (starts with provider prefix) + if any( + output_name.startswith(prefix) for prefix in provider_prefixes + ): + continue + # Resolve output to actual resources + target_resources = resolve_module_output_to_resources( + ref_module_name, output_name, tfdata + ) + # Create connections + for origin in module_resources: + for dest in target_resources: + if origin in graphdict and dest not in graphdict[origin]: + add_connection(graphdict, origin, dest) + + +def resolve_module_output_to_resources( + module_name: str, output_name: str, tfdata: Dict[str, Any] +) -> List[str]: + """Resolve module output reference to actual resource names. + + Args: + module_name: Name of the module being referenced + output_name: Name of the output variable + tfdata: Terraform data dictionary + + Returns: + List of actual resource names that the output references + """ + resources = [] + # Search through output files for matching module + for file in tfdata.get("all_output", {}).keys(): + if f";{module_name};" in file: + for output_dict in tfdata["all_output"][file]: + if output_name in output_dict: + output_value = output_dict[output_name].get("value", "") + # Extract resource references from output value + resource_refs = helpers.extract_terraform_resource( + str(output_value) + ) + for ref in resource_refs: + # Find matching nodes in node_list + matching = [n for n in tfdata["node_list"] if ref in n] + resources.extend(matching) + break + return resources + + def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: """Build final graph structure by detecting resource relationships. @@ -275,7 +382,9 @@ def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: if nodename not in tfdata["meta_data"].keys(): if node in tfdata["original_metadata"]: dg = dict_generator(tfdata["original_metadata"][node]) - tfdata["meta_data"][node] = copy.deepcopy(tfdata["original_metadata"][node]) + tfdata["meta_data"][node] = copy.deepcopy( + tfdata["original_metadata"][node] + ) else: dg = dict_generator(tfdata["meta_data"][nodename]) @@ -540,7 +649,11 @@ def needs_multiple(resource: str, parent: str, tfdata: Dict[str, Any]) -> bool: ) else: security_group_with_count = False - has_variant = helpers.check_variant(resource, tfdata["meta_data"][resource]) if resource in tfdata["meta_data"] else False + has_variant = ( + helpers.check_variant(resource, tfdata["meta_data"][resource]) + if resource in tfdata["meta_data"] + else False + ) not_unique_resource = "aws_route_table." not in resource if ( ( From afae8d9e661476e70767db63a1352eb28ca98078 Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 08:15:46 +0000 Subject: [PATCH 2/8] refactor check_relationship --- architecture.json | 256 +++++++++++++++++++++++++++++++++++++++ modules/graphmaker.py | 274 ++++++++++++++++++++++++++++-------------- 2 files changed, 437 insertions(+), 93 deletions(-) create mode 100644 architecture.json diff --git a/architecture.json b/architecture.json new file mode 100644 index 0000000..3517a47 --- /dev/null +++ b/architecture.json @@ -0,0 +1,256 @@ +{ + "aws_acm_certificate.acm": [], + "aws_alb.elb~1": [ + "aws_fargate.ecs~1" + ], + "aws_alb.elb~2": [ + "aws_fargate.ecs~2" + ], + "aws_alb.elb~3": [ + "aws_fargate.ecs~3" + ], + "aws_appautoscaling_policy.scale_down": [ + "aws_cloudwatch_log_group.cloudwatch" + ], + "aws_appautoscaling_policy.scale_up": [ + "aws_cloudwatch_log_group.cloudwatch" + ], + "aws_appautoscaling_target.this~1": [ + "aws_appautoscaling_policy.scale_down", + "aws_appautoscaling_policy.scale_up", + "aws_fargate.ecs~1" + ], + "aws_appautoscaling_target.this~2": [ + "aws_appautoscaling_policy.scale_down", + "aws_appautoscaling_policy.scale_up", + "aws_fargate.ecs~2" + ], + "aws_appautoscaling_target.this~3": [ + "aws_appautoscaling_policy.scale_down", + "aws_appautoscaling_policy.scale_up", + "aws_fargate.ecs~3" + ], + "aws_az.availability_zone_us_east_1a~1": [ + "module.vpc.aws_subnet.private[0]~1", + "module.vpc.aws_subnet.public[0]~1" + ], + "aws_az.availability_zone_us_east_1b~2": [ + "module.vpc.aws_subnet.private[1]~2", + "module.vpc.aws_subnet.public[1]~2" + ], + "aws_az.availability_zone_us_east_1c~3": [ + "module.vpc.aws_subnet.private[2]~3", + "module.vpc.aws_subnet.public[2]~3" + ], + "aws_cloudfront_distribution.this": [ + "aws_acm_certificate.acm", + "aws_acm_certificate.acm", + "aws_fargate.ecs~1", + "aws_fargate.ecs~2", + "aws_fargate.ecs~3", + "aws_lb.elb", + "aws_route53_record.route_53", + "aws_route53_record.route_53" + ], + "aws_cloudwatch_log_group.cloudwatch": [ + "aws_fargate.ecs~1", + "aws_fargate.ecs~2", + "aws_fargate.ecs~3" + ], + "aws_db_subnet_group.this": [ + "aws_rds_aurora.this", + "aws_rds_aurora.this" + ], + "aws_ecr_repository.ecr": [], + "aws_ecs_cluster.ecs": [], + "aws_efs_file_system.efs": [], + "aws_efs_mount_target.this[0]~1": [ + "aws_efs_file_system.efs" + ], + "aws_efs_mount_target.this[1]~2": [ + "aws_efs_file_system.efs" + ], + "aws_efs_mount_target.this[2]~3": [ + "aws_efs_file_system.efs" + ], + "aws_eip.elastic_ip": [ + "aws_internet_gateway.igw" + ], + "aws_fargate.ecs~1": [ + "aws_ecr_repository.ecr", + "aws_ecs_cluster.ecs", + "aws_efs_mount_target.this", + "aws_efs_mount_target.this[0]~1", + "aws_rds_aurora.this", + "aws_rds_aurora.this" + ], + "aws_fargate.ecs~2": [ + "aws_ecr_repository.ecr", + "aws_ecs_cluster.ecs", + "aws_efs_mount_target.this", + "aws_efs_mount_target.this[1]~2", + "aws_rds_aurora.this", + "aws_rds_aurora.this" + ], + "aws_fargate.ecs~3": [ + "aws_ecr_repository.ecr", + "aws_ecs_cluster.ecs", + "aws_efs_mount_target.this", + "aws_efs_mount_target.this[2]~3", + "aws_rds_aurora.this", + "aws_rds_aurora.this" + ], + "aws_group.shared_services": [ + "aws_acm_certificate.acm", + "aws_cloudwatch_log_group.cloudwatch", + "aws_ecr_repository.ecr", + "aws_efs_file_system.efs", + "aws_eip.elastic_ip", + "aws_ssm_parameter.ssmparam" + ], + "aws_iam_policy.task_execution_policy": [ + "aws_iam_role_policy_attachment.task_execution_policy_attach" + ], + "aws_iam_policy.task_policy": [ + "aws_iam_role_policy_attachment.task_policy_attach" + ], + "aws_iam_role.task_execution_role": [ + "aws_fargate.ecs~1", + "aws_fargate.ecs~2", + "aws_fargate.ecs~3", + "aws_iam_role_policy_attachment.task_execution_policy_attach" + ], + "aws_iam_role.task_role": [ + "aws_fargate.ecs~1", + "aws_fargate.ecs~2", + "aws_fargate.ecs~3", + "aws_iam_role_policy_attachment.task_policy_attach" + ], + "aws_iam_role_policy_attachment.task_execution_policy_attach": [], + "aws_iam_role_policy_attachment.task_policy_attach": [], + "aws_internet_gateway.igw": [ + "tv_aws_internet.internet" + ], + "aws_lb.elb": [ + "aws_acm_certificate.acm", + "aws_alb.elb~1", + "aws_alb.elb~2", + "aws_alb.elb~3" + ], + "aws_rds_aurora.this": [], + "aws_route53_record.route_53": [ + "aws_acm_certificate.acm" + ], + "aws_security_group.alb_elb~1": [ + "aws_alb.elb~1" + ], + "aws_security_group.alb_elb~2": [ + "aws_alb.elb~2" + ], + "aws_security_group.alb_elb~3": [ + "aws_alb.elb~3" + ], + "aws_security_group.efs~1": [ + "aws_efs_mount_target.this[0]~1" + ], + "aws_security_group.efs~2": [ + "aws_efs_mount_target.this[1]~2" + ], + "aws_security_group.efs~3": [ + "aws_efs_mount_target.this[2]~3" + ], + "aws_ssm_parameter.ssmparam": [ + "aws_fargate.ecs~1", + "aws_fargate.ecs~2", + "aws_fargate.ecs~3" + ], + "module.vpc.aws_default_network_acl.this[0]~1": [], + "module.vpc.aws_default_route_table.default[0]~1": [], + "module.vpc.aws_default_security_group.this[0]~1": [], + "module.vpc.aws_nat_gateway.this[0]~1": [ + "aws_eip.elastic_ip", + "aws_internet_gateway.igw", + "aws_internet_gateway.igw" + ], + "module.vpc.aws_nat_gateway.this[1]~2": [ + "aws_eip.elastic_ip", + "aws_internet_gateway.igw" + ], + "module.vpc.aws_nat_gateway.this[2]~3": [ + "aws_eip.elastic_ip", + "aws_internet_gateway.igw" + ], + "module.vpc.aws_route.private_nat_gateway[0]~1": [ + "module.vpc.aws_nat_gateway.this[0]~1", + "module.vpc.aws_route_table.private[0]~1" + ], + "module.vpc.aws_route.private_nat_gateway[1]~2": [ + "module.vpc.aws_nat_gateway.this[1]~2", + "module.vpc.aws_route_table.private[1]~2" + ], + "module.vpc.aws_route.private_nat_gateway[2]~3": [ + "module.vpc.aws_nat_gateway.this[2]~3", + "module.vpc.aws_route_table.private[2]~3" + ], + "module.vpc.aws_route.public_internet_gateway[0]~1": [ + "module.vpc.aws_route_table.public[0]~1" + ], + "module.vpc.aws_route_table.private[0]~1": [], + "module.vpc.aws_route_table.private[1]~2": [], + "module.vpc.aws_route_table.private[2]~3": [], + "module.vpc.aws_route_table.public[0]~1": [], + "module.vpc.aws_route_table_association.private[0]~1": [ + "module.vpc.aws_route_table.private[0]~1" + ], + "module.vpc.aws_route_table_association.private[1]~2": [ + "module.vpc.aws_route_table.private[1]~2" + ], + "module.vpc.aws_route_table_association.private[2]~3": [ + "module.vpc.aws_route_table.private[2]~3" + ], + "module.vpc.aws_route_table_association.public[0]~1": [ + "module.vpc.aws_route_table.public[0]~1" + ], + "module.vpc.aws_route_table_association.public[1]~2": [], + "module.vpc.aws_route_table_association.public[2]~3": [], + "module.vpc.aws_subnet.private[0]~1": [ + "aws_appautoscaling_target.this~1", + "aws_security_group.efs~1", + "module.vpc.aws_route_table_association.private[0]~1" + ], + "module.vpc.aws_subnet.private[1]~2": [ + "aws_appautoscaling_target.this~2", + "aws_security_group.efs~2", + "module.vpc.aws_route_table_association.private[1]~2" + ], + "module.vpc.aws_subnet.private[2]~3": [ + "aws_appautoscaling_target.this~3", + "aws_security_group.efs~3", + "module.vpc.aws_route_table_association.private[2]~3" + ], + "module.vpc.aws_subnet.public[0]~1": [ + "aws_security_group.alb_elb~1", + "module.vpc.aws_nat_gateway.this[0]~1", + "module.vpc.aws_route_table_association.public[0]~1" + ], + "module.vpc.aws_subnet.public[1]~2": [ + "aws_security_group.alb_elb~2", + "module.vpc.aws_nat_gateway.this[1]~2", + "module.vpc.aws_route_table_association.public[1]~2" + ], + "module.vpc.aws_subnet.public[2]~3": [ + "aws_security_group.alb_elb~3", + "module.vpc.aws_nat_gateway.this[2]~3", + "module.vpc.aws_route_table_association.public[2]~3" + ], + "module.vpc.aws_vpc.this[0]~1": [ + "aws_az.availability_zone_us_east_1a~1", + "aws_az.availability_zone_us_east_1b~2", + "aws_az.availability_zone_us_east_1c~3", + "aws_lb.elb" + ], + "tv_aws_internet.internet": [], + "tv_aws_users.users": [ + "aws_route53_record.route_53" + ] +} \ No newline at end of file diff --git a/modules/graphmaker.py b/modules/graphmaker.py index 8bf585a..36f143b 100644 --- a/modules/graphmaker.py +++ b/modules/graphmaker.py @@ -103,6 +103,150 @@ def reverse_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: return tfdata +def _find_implied_connections( + param: str, nodes: List[str], IMPLIED_CONNECTIONS: Dict +) -> List[str]: + """Find implied connections based on keywords. + + Args: + param: Parameter value to search for keywords + nodes: List of all resource nodes + IMPLIED_CONNECTIONS: Dictionary of implied connection keywords + + Returns: + List of matching resource names from implied connections + """ + matching = [] + # Check for implied connections based on keywords + found_connection = list({s for s in IMPLIED_CONNECTIONS.keys() if s in str(param)}) + if found_connection: + for n in nodes: + if helpers.get_no_module_name(n).startswith( + IMPLIED_CONNECTIONS[found_connection[0]] + ): + matching.append(n) + return matching + + +def _find_matching_resources(param: str, nodes: List[str]) -> List[str]: + """Find resources that match the parameter value. + + Args: + param: Parameter value to search for references + nodes: List of all resource nodes + + Returns: + List of matching resource names + """ + matching = [] + + # Handle list references (e.g., resource[0]) + if re.search(r"\[\d+\]", param) and "[*]" not in param and param != "[]": + matching = list( + {s for s in nodes if s.split("~")[0] in param.replace(".*", "")} + ) + else: + # Extract Terraform resource references from parameter + extracted_resources_list = helpers.extract_terraform_resource(param) + if extracted_resources_list: + for r in extracted_resources_list: + matching.extend( + list( + { + s + for s in nodes + if (r in s or helpers.cleanup_curlies(r) in s) + and s not in matching + } + ) + ) + + return matching + + +def _should_reverse_arrow( + param: str, resource_associated_with: str, REVERSE_ARROW_LIST: List[str] +) -> bool: + """Determine if arrow direction should be reversed. + + Args: + param: Parameter value being checked + resource_associated_with: Resource name being checked + REVERSE_ARROW_LIST: List of patterns that trigger arrow reversal + + Returns: + True if arrow should be reversed + """ + reverse_origin_match = [s for s in REVERSE_ARROW_LIST if s in str(param)] + if len(reverse_origin_match) == 0: + return False + + # Prevent double reversal if both sides match + reverse_dest_match = [ + s for s in REVERSE_ARROW_LIST if s in resource_associated_with + ] + if len(reverse_dest_match) > 0: + if REVERSE_ARROW_LIST.index(reverse_dest_match[0]) < REVERSE_ARROW_LIST.index( + reverse_origin_match[0] + ): + return False + + return True + + +def _numbered_nodes_match(matched_resource: str, resource_associated_with: str) -> bool: + """Check if numbered nodes have matching suffixes. + + Args: + matched_resource: First resource name + resource_associated_with: Second resource name + + Returns: + True if both have ~ suffix and suffixes match, or if no suffix check needed + """ + # Match numbered nodes with same suffix + if "~" in matched_resource and "~" in resource_associated_with: + matched_resource_no = matched_resource.split("~")[1] + resource_associated_with_no = resource_associated_with.split("~")[1] + if matched_resource_no != resource_associated_with_no: + return False + return True + + +def _add_connection_pair( + connection_pairs: List[str], + matched_resource: str, + resource_associated_with: str, + reverse: bool, + tfdata: Dict[str, Any], +) -> None: + """Add connection pair in appropriate direction. + + Args: + connection_pairs: List to append connection pairs to + matched_resource: Matched resource name + resource_associated_with: Origin resource name + reverse: Whether to reverse arrow direction + tfdata: Terraform data dictionary + """ + if reverse: + # Reversed: matched -> resource + if ( + resource_associated_with not in tfdata["graphdict"][matched_resource] + and matched_resource not in tfdata["graphdict"][resource_associated_with] + ): + connection_pairs.append(matched_resource) + connection_pairs.append(resource_associated_with) + else: + # Normal: resource -> matched + if ( + matched_resource not in tfdata["graphdict"][resource_associated_with] + and matched_resource not in connection_pairs + ): + connection_pairs.append(resource_associated_with) + connection_pairs.append(matched_resource) + + def check_relationship( resource_associated_with: str, plist: List[Any], tfdata: Dict[str, Any] ) -> List[str]: @@ -127,105 +271,36 @@ def check_relationship( nodes = tfdata["node_list"] hidden = tfdata["hidden"] connection_pairs: List[str] = list() - matching: List[str] = list() # Scan each parameter for resource references for p in plist: param = str(p) - matching = [] - - # Handle list references (e.g., resource[0]) - if re.search(r"\[\d+\]", param) and "[*]" not in param and param != "[]": - matching = list( - {s for s in nodes if s.split("~")[0] in param.replace(".*", "")} - ) - pass - else: - # Extract Terraform resource references from parameter - extracted_resources_list = helpers.extract_terraform_resource(param) - if extracted_resources_list: - for r in extracted_resources_list: - matching.extend( - list( - { - s - for s in nodes - if (r in s or helpers.cleanup_curlies(r) in s) - and s not in matching - } - ) - ) - - # Check for implied connections based on keywords - found_connection = list( - {s for s in IMPLIED_CONNECTIONS.keys() if s in str(param)} - ) - if found_connection: - for n in nodes: - if ( - helpers.get_no_module_name(n).startswith( - IMPLIED_CONNECTIONS[found_connection[0]] - ) - and n not in matching - ): - matching.append(n) + matching = _find_matching_resources(param, nodes) + implied = _find_implied_connections(param, nodes, IMPLIED_CONNECTIONS) + # Combine explicit and implied matches, avoiding duplicates + matching.extend([m for m in implied if m not in matching]) # Process matched resources - if matching: - for matched_resource in matching: - reverse = False - # Skip hidden resources - if ( - matched_resource not in hidden - and resource_associated_with not in hidden - ): - # Check if arrow direction should be reversed - reverse_origin_match = [ - s for s in REVERSE_ARROW_LIST if s in str(param) - ] - if len(reverse_origin_match) > 0: - reverse = True - # Prevent double reversal if both sides match - reverse_dest_match = [ - s - for s in REVERSE_ARROW_LIST - if s in resource_associated_with - ] - if len(reverse_dest_match) > 0: - if REVERSE_ARROW_LIST.index( - reverse_dest_match[0] - ) < REVERSE_ARROW_LIST.index(reverse_origin_match[0]): - reverse = False - - # Match numbered nodes with same suffix - if "~" in matched_resource and "~" in resource_associated_with: - matched_resource_no = matched_resource.split("~")[1] - resource_associated_with_no = resource_associated_with.split( - "~" - )[1] - if matched_resource_no != resource_associated_with_no: - continue - - # Add connection pair in appropriate direction - if reverse: - # Reversed: matched -> resource - if ( - resource_associated_with - not in tfdata["graphdict"][matched_resource] - and matched_resource - not in tfdata["graphdict"][resource_associated_with] - ): - connection_pairs.append(matched_resource) - connection_pairs.append(resource_associated_with) - else: - # Normal: resource -> matched - if ( - matched_resource - not in tfdata["graphdict"][resource_associated_with] - and matched_resource not in connection_pairs - ): - connection_pairs.append(resource_associated_with) - connection_pairs.append(matched_resource) + for matched_resource in matching: + # Skip hidden resources + if ( + matched_resource not in hidden + and resource_associated_with not in hidden + and _numbered_nodes_match(matched_resource, resource_associated_with) + ): + # Check if arrow direction should be reversed + reverse = _should_reverse_arrow( + param, resource_associated_with, REVERSE_ARROW_LIST + ) + + # Add connection pair in appropriate direction + _add_connection_pair( + connection_pairs, + matched_resource, + resource_associated_with, + reverse, + tfdata, + ) return connection_pairs @@ -305,6 +380,19 @@ def scan_module_relationships( add_connection(graphdict, origin, dest) +def add_connection(graphdict: Dict, origin: str, dest: str) -> None: + """Add connection between origin and dest nodes.""" + if dest in graphdict[origin] or helpers.get_no_module_name(origin).startswith( + "aws_security_group" + ): + return + click.echo(f" {origin} --> {dest}") + graphdict[origin].append(dest) + # Replace unnumbered with numbered version + if "~" in origin and "~" in dest and dest.split("~")[0] in graphdict[origin]: + graphdict[origin].remove(dest.split("~")[0]) + + def resolve_module_output_to_resources( module_name: str, output_name: str, tfdata: Dict[str, Any] ) -> List[str]: From c6257e1cd0dc15daa0a442a7161612f0cd17bafc Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 08:27:14 +0000 Subject: [PATCH 3/8] added cross module reference check --- architecture.json | 262 +----------------- modules/graphmaker.py | 41 ++- .../aws_terraform/static-website/main.tf | 72 +++++ .../aws_terraform/static-website/outputs.tf | 14 + .../aws_terraform/static-website/variables.tf | 11 + 5 files changed, 139 insertions(+), 261 deletions(-) create mode 100644 tests/fixtures/aws_terraform/static-website/main.tf create mode 100644 tests/fixtures/aws_terraform/static-website/outputs.tf create mode 100644 tests/fixtures/aws_terraform/static-website/variables.tf diff --git a/architecture.json b/architecture.json index 3517a47..b1fa3ac 100644 --- a/architecture.json +++ b/architecture.json @@ -1,256 +1,10 @@ { - "aws_acm_certificate.acm": [], - "aws_alb.elb~1": [ - "aws_fargate.ecs~1" - ], - "aws_alb.elb~2": [ - "aws_fargate.ecs~2" - ], - "aws_alb.elb~3": [ - "aws_fargate.ecs~3" - ], - "aws_appautoscaling_policy.scale_down": [ - "aws_cloudwatch_log_group.cloudwatch" - ], - "aws_appautoscaling_policy.scale_up": [ - "aws_cloudwatch_log_group.cloudwatch" - ], - "aws_appautoscaling_target.this~1": [ - "aws_appautoscaling_policy.scale_down", - "aws_appautoscaling_policy.scale_up", - "aws_fargate.ecs~1" - ], - "aws_appautoscaling_target.this~2": [ - "aws_appautoscaling_policy.scale_down", - "aws_appautoscaling_policy.scale_up", - "aws_fargate.ecs~2" - ], - "aws_appautoscaling_target.this~3": [ - "aws_appautoscaling_policy.scale_down", - "aws_appautoscaling_policy.scale_up", - "aws_fargate.ecs~3" - ], - "aws_az.availability_zone_us_east_1a~1": [ - "module.vpc.aws_subnet.private[0]~1", - "module.vpc.aws_subnet.public[0]~1" - ], - "aws_az.availability_zone_us_east_1b~2": [ - "module.vpc.aws_subnet.private[1]~2", - "module.vpc.aws_subnet.public[1]~2" - ], - "aws_az.availability_zone_us_east_1c~3": [ - "module.vpc.aws_subnet.private[2]~3", - "module.vpc.aws_subnet.public[2]~3" - ], - "aws_cloudfront_distribution.this": [ - "aws_acm_certificate.acm", - "aws_acm_certificate.acm", - "aws_fargate.ecs~1", - "aws_fargate.ecs~2", - "aws_fargate.ecs~3", - "aws_lb.elb", - "aws_route53_record.route_53", - "aws_route53_record.route_53" - ], - "aws_cloudwatch_log_group.cloudwatch": [ - "aws_fargate.ecs~1", - "aws_fargate.ecs~2", - "aws_fargate.ecs~3" - ], - "aws_db_subnet_group.this": [ - "aws_rds_aurora.this", - "aws_rds_aurora.this" - ], - "aws_ecr_repository.ecr": [], - "aws_ecs_cluster.ecs": [], - "aws_efs_file_system.efs": [], - "aws_efs_mount_target.this[0]~1": [ - "aws_efs_file_system.efs" - ], - "aws_efs_mount_target.this[1]~2": [ - "aws_efs_file_system.efs" - ], - "aws_efs_mount_target.this[2]~3": [ - "aws_efs_file_system.efs" - ], - "aws_eip.elastic_ip": [ - "aws_internet_gateway.igw" - ], - "aws_fargate.ecs~1": [ - "aws_ecr_repository.ecr", - "aws_ecs_cluster.ecs", - "aws_efs_mount_target.this", - "aws_efs_mount_target.this[0]~1", - "aws_rds_aurora.this", - "aws_rds_aurora.this" - ], - "aws_fargate.ecs~2": [ - "aws_ecr_repository.ecr", - "aws_ecs_cluster.ecs", - "aws_efs_mount_target.this", - "aws_efs_mount_target.this[1]~2", - "aws_rds_aurora.this", - "aws_rds_aurora.this" - ], - "aws_fargate.ecs~3": [ - "aws_ecr_repository.ecr", - "aws_ecs_cluster.ecs", - "aws_efs_mount_target.this", - "aws_efs_mount_target.this[2]~3", - "aws_rds_aurora.this", - "aws_rds_aurora.this" - ], - "aws_group.shared_services": [ - "aws_acm_certificate.acm", - "aws_cloudwatch_log_group.cloudwatch", - "aws_ecr_repository.ecr", - "aws_efs_file_system.efs", - "aws_eip.elastic_ip", - "aws_ssm_parameter.ssmparam" - ], - "aws_iam_policy.task_execution_policy": [ - "aws_iam_role_policy_attachment.task_execution_policy_attach" - ], - "aws_iam_policy.task_policy": [ - "aws_iam_role_policy_attachment.task_policy_attach" - ], - "aws_iam_role.task_execution_role": [ - "aws_fargate.ecs~1", - "aws_fargate.ecs~2", - "aws_fargate.ecs~3", - "aws_iam_role_policy_attachment.task_execution_policy_attach" - ], - "aws_iam_role.task_role": [ - "aws_fargate.ecs~1", - "aws_fargate.ecs~2", - "aws_fargate.ecs~3", - "aws_iam_role_policy_attachment.task_policy_attach" - ], - "aws_iam_role_policy_attachment.task_execution_policy_attach": [], - "aws_iam_role_policy_attachment.task_policy_attach": [], - "aws_internet_gateway.igw": [ - "tv_aws_internet.internet" - ], - "aws_lb.elb": [ - "aws_acm_certificate.acm", - "aws_alb.elb~1", - "aws_alb.elb~2", - "aws_alb.elb~3" - ], - "aws_rds_aurora.this": [], - "aws_route53_record.route_53": [ - "aws_acm_certificate.acm" - ], - "aws_security_group.alb_elb~1": [ - "aws_alb.elb~1" - ], - "aws_security_group.alb_elb~2": [ - "aws_alb.elb~2" - ], - "aws_security_group.alb_elb~3": [ - "aws_alb.elb~3" - ], - "aws_security_group.efs~1": [ - "aws_efs_mount_target.this[0]~1" - ], - "aws_security_group.efs~2": [ - "aws_efs_mount_target.this[1]~2" - ], - "aws_security_group.efs~3": [ - "aws_efs_mount_target.this[2]~3" - ], - "aws_ssm_parameter.ssmparam": [ - "aws_fargate.ecs~1", - "aws_fargate.ecs~2", - "aws_fargate.ecs~3" - ], - "module.vpc.aws_default_network_acl.this[0]~1": [], - "module.vpc.aws_default_route_table.default[0]~1": [], - "module.vpc.aws_default_security_group.this[0]~1": [], - "module.vpc.aws_nat_gateway.this[0]~1": [ - "aws_eip.elastic_ip", - "aws_internet_gateway.igw", - "aws_internet_gateway.igw" - ], - "module.vpc.aws_nat_gateway.this[1]~2": [ - "aws_eip.elastic_ip", - "aws_internet_gateway.igw" - ], - "module.vpc.aws_nat_gateway.this[2]~3": [ - "aws_eip.elastic_ip", - "aws_internet_gateway.igw" - ], - "module.vpc.aws_route.private_nat_gateway[0]~1": [ - "module.vpc.aws_nat_gateway.this[0]~1", - "module.vpc.aws_route_table.private[0]~1" - ], - "module.vpc.aws_route.private_nat_gateway[1]~2": [ - "module.vpc.aws_nat_gateway.this[1]~2", - "module.vpc.aws_route_table.private[1]~2" - ], - "module.vpc.aws_route.private_nat_gateway[2]~3": [ - "module.vpc.aws_nat_gateway.this[2]~3", - "module.vpc.aws_route_table.private[2]~3" - ], - "module.vpc.aws_route.public_internet_gateway[0]~1": [ - "module.vpc.aws_route_table.public[0]~1" - ], - "module.vpc.aws_route_table.private[0]~1": [], - "module.vpc.aws_route_table.private[1]~2": [], - "module.vpc.aws_route_table.private[2]~3": [], - "module.vpc.aws_route_table.public[0]~1": [], - "module.vpc.aws_route_table_association.private[0]~1": [ - "module.vpc.aws_route_table.private[0]~1" - ], - "module.vpc.aws_route_table_association.private[1]~2": [ - "module.vpc.aws_route_table.private[1]~2" - ], - "module.vpc.aws_route_table_association.private[2]~3": [ - "module.vpc.aws_route_table.private[2]~3" - ], - "module.vpc.aws_route_table_association.public[0]~1": [ - "module.vpc.aws_route_table.public[0]~1" - ], - "module.vpc.aws_route_table_association.public[1]~2": [], - "module.vpc.aws_route_table_association.public[2]~3": [], - "module.vpc.aws_subnet.private[0]~1": [ - "aws_appautoscaling_target.this~1", - "aws_security_group.efs~1", - "module.vpc.aws_route_table_association.private[0]~1" - ], - "module.vpc.aws_subnet.private[1]~2": [ - "aws_appautoscaling_target.this~2", - "aws_security_group.efs~2", - "module.vpc.aws_route_table_association.private[1]~2" - ], - "module.vpc.aws_subnet.private[2]~3": [ - "aws_appautoscaling_target.this~3", - "aws_security_group.efs~3", - "module.vpc.aws_route_table_association.private[2]~3" - ], - "module.vpc.aws_subnet.public[0]~1": [ - "aws_security_group.alb_elb~1", - "module.vpc.aws_nat_gateway.this[0]~1", - "module.vpc.aws_route_table_association.public[0]~1" - ], - "module.vpc.aws_subnet.public[1]~2": [ - "aws_security_group.alb_elb~2", - "module.vpc.aws_nat_gateway.this[1]~2", - "module.vpc.aws_route_table_association.public[1]~2" - ], - "module.vpc.aws_subnet.public[2]~3": [ - "aws_security_group.alb_elb~3", - "module.vpc.aws_nat_gateway.this[2]~3", - "module.vpc.aws_route_table_association.public[2]~3" - ], - "module.vpc.aws_vpc.this[0]~1": [ - "aws_az.availability_zone_us_east_1a~1", - "aws_az.availability_zone_us_east_1b~2", - "aws_az.availability_zone_us_east_1c~3", - "aws_lb.elb" - ], - "tv_aws_internet.internet": [], - "tv_aws_users.users": [ - "aws_route53_record.route_53" - ] + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": [ + "module.s3_bucket.aws_s3_bucket.this[0]~1" + ], + "module.s3_bucket.aws_s3_bucket.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": [] } \ No newline at end of file diff --git a/modules/graphmaker.py b/modules/graphmaker.py index 36f143b..0a854f9 100644 --- a/modules/graphmaker.py +++ b/modules/graphmaker.py @@ -312,9 +312,11 @@ def scan_module_relationships( if not tfdata.get("all_module"): return - # Get provider prefixes for multi-cloud support + # Get provider prefixes and GROUP_NODES for multi-cloud support config = _get_provider_config(tfdata) + constants = _load_config_constants(tfdata) provider_prefixes = config.PROVIDER_PREFIX # e.g., ["aws_", "google_", "azurerm_"] + GROUP_NODES = constants["GROUP_NODES"] # Build regex pattern for any provider resource (e.g., aws_|google_|azurerm_) provider_pattern = "|".join([p.replace("_", "\_") for p in provider_prefixes]) @@ -353,11 +355,22 @@ def scan_module_relationships( target_resources = [ n for n in tfdata["node_list"] if target_pattern in n ] - # Create connections + # Create connections, excluding GROUP nodes for origin in module_resources: for dest in target_resources: - if origin in graphdict and dest not in graphdict[origin]: - add_connection(graphdict, origin, dest) + origin_type = helpers.get_no_module_name(origin).split(".")[ + 0 + ] + dest_type = helpers.get_no_module_name(dest).split(".")[0] + if ( + origin_type not in GROUP_NODES + and dest_type not in GROUP_NODES + ): + if ( + origin in graphdict + and dest not in graphdict[origin] + ): + add_connection(graphdict, origin, dest) # Find module output references (e.g., module.s3_bucket.bucket_id) module_output_refs = re.findall(r"module\.(\w+)\.(\w+)", metadata_str) @@ -373,11 +386,22 @@ def scan_module_relationships( target_resources = resolve_module_output_to_resources( ref_module_name, output_name, tfdata ) - # Create connections + # Create connections, excluding GROUP nodes for origin in module_resources: for dest in target_resources: - if origin in graphdict and dest not in graphdict[origin]: - add_connection(graphdict, origin, dest) + origin_type = helpers.get_no_module_name(origin).split(".")[ + 0 + ] + dest_type = helpers.get_no_module_name(dest).split(".")[0] + if ( + origin_type not in GROUP_NODES + and dest_type not in GROUP_NODES + ): + if ( + origin in graphdict + and dest not in graphdict[origin] + ): + add_connection(graphdict, origin, dest) def add_connection(graphdict: Dict, origin: str, dest: str) -> None: @@ -512,6 +536,9 @@ def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: if hidden_resource in graphdict[resource]: graphdict[resource].remove(hidden_resource) + # Scan module-to-module relationships + scan_module_relationships(tfdata, graphdict) + tfdata["graphdict"] = graphdict # Store immutable snapshot for reference tfdata["original_graphdict_with_relations"] = copy.deepcopy(graphdict) diff --git a/tests/fixtures/aws_terraform/static-website/main.tf b/tests/fixtures/aws_terraform/static-website/main.tf new file mode 100644 index 0000000..0263d26 --- /dev/null +++ b/tests/fixtures/aws_terraform/static-website/main.tf @@ -0,0 +1,72 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = var.aws_region +} + +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "~> 3.0" + + bucket = var.bucket_name + acl = "private" + + versioning = { + enabled = true + } + + website = { + index_document = "index.html" + error_document = "error.html" + } + + block_public_acls = false + block_public_policy = false + ignore_public_acls = false + restrict_public_buckets = false +} + +module "cloudfront" { + source = "terraform-aws-modules/cloudfront/aws" + version = "~> 3.0" + + comment = "CloudFront distribution for ${var.bucket_name}" + enabled = true + is_ipv6_enabled = true + price_class = "PriceClass_100" + default_root_object = "index.html" + + origin = { + s3_bucket = { + domain_name = module.s3_bucket.s3_bucket_bucket_regional_domain_name + origin_id = "S3-${var.bucket_name}" + } + } + + default_cache_behavior = { + target_origin_id = "S3-${var.bucket_name}" + viewer_protocol_policy = "redirect-to-https" + allowed_methods = ["GET", "HEAD"] + cached_methods = ["GET", "HEAD"] + compress = true + + forwarded_values = { + query_string = false + cookies = { + forward = "none" + } + } + } + + viewer_certificate = { + cloudfront_default_certificate = true + } +} diff --git a/tests/fixtures/aws_terraform/static-website/outputs.tf b/tests/fixtures/aws_terraform/static-website/outputs.tf new file mode 100644 index 0000000..0a19962 --- /dev/null +++ b/tests/fixtures/aws_terraform/static-website/outputs.tf @@ -0,0 +1,14 @@ +output "cloudfront_distribution_domain_name" { + description = "CloudFront distribution domain name" + value = module.cloudfront.cloudfront_distribution_domain_name +} + +output "s3_bucket_name" { + description = "S3 bucket name" + value = module.s3_bucket.s3_bucket_id +} + +output "website_url" { + description = "Website URL" + value = "https://${module.cloudfront.cloudfront_distribution_domain_name}" +} diff --git a/tests/fixtures/aws_terraform/static-website/variables.tf b/tests/fixtures/aws_terraform/static-website/variables.tf new file mode 100644 index 0000000..4a1c8a0 --- /dev/null +++ b/tests/fixtures/aws_terraform/static-website/variables.tf @@ -0,0 +1,11 @@ +variable "aws_region" { + description = "AWS region" + type = string + default = "us-east-1" +} + +variable "bucket_name" { + description = "S3 bucket name for static website" + type = string + default = "my-react-static-website" +} From 52acb2e98f4ae8c4139e9314be5a94669c7ef9ce Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 08:43:10 +0000 Subject: [PATCH 4/8] refactored add_relations() --- modules/graphmaker.py | 178 ++++++++++++++++++++++++++---------------- 1 file changed, 111 insertions(+), 67 deletions(-) diff --git a/modules/graphmaker.py b/modules/graphmaker.py index 0a854f9..dac5c80 100644 --- a/modules/graphmaker.py +++ b/modules/graphmaker.py @@ -449,10 +449,112 @@ def resolve_module_output_to_resources( return resources +def _get_base_node_name(node: str, tfdata: Dict[str, Any]) -> str: + """Determine base node name by stripping suffixes.""" + if node not in tfdata["meta_data"].keys(): + nodename = node.split("~")[0] + if "[" in nodename: + nodename = nodename.split("[")[0] + else: + nodename = node + return nodename + + +def _should_skip_node(node: str, nodename: str) -> bool: + """Check if node should be skipped during relationship scanning.""" + return ( + helpers.get_no_module_name(nodename).startswith("random") + or helpers.get_no_module_name(node).startswith("aws_security_group") + or helpers.get_no_module_name(node).startswith("null") + ) + + +def _get_metadata_generator(node: str, nodename: str, tfdata: Dict[str, Any]): + """Get metadata generator for parameter scanning. + + Note: Mutates tfdata["meta_data"] by copying from original_metadata if needed. + """ + if nodename not in tfdata["meta_data"].keys(): + if node in tfdata["original_metadata"]: + # Mutation: populate meta_data from original_metadata + tfdata["meta_data"][node] = copy.deepcopy(tfdata["original_metadata"][node]) + return dict_generator(tfdata["original_metadata"][node]) + return dict_generator(tfdata["meta_data"][nodename]) + + +def _process_connection_pairs( + matching_result: List[str], tfdata: Dict[str, Any] +) -> Dict[str, Any]: + """Process connection pairs and add to graphdict. + + Returns mutated tfdata. + """ + for i in range(0, len(matching_result), 2): + origin = matching_result[i] + dest = matching_result[i + 1] + c_list = list(tfdata["graphdict"][origin]) + # Add connection if not exists and not security group + if dest not in c_list and not helpers.get_no_module_name(origin).startswith( + "aws_security_group" + ): + click.echo(f" {origin} --> {dest}") + c_list.append(dest) + # Replace unnumbered with numbered version + if "~" in origin and "~" in dest and dest.split("~")[0] in c_list: + c_list.remove(dest.split("~")[0]) + # Update graphdict with new connections + tfdata["graphdict"][origin] = c_list + + return tfdata + + +def _scan_node_relationships(tfdata: Dict[str, Any]) -> Dict[str, Any]: + """Scan each node for relationships with other resources. + + Returns mutated tfdata. + """ + for node in tfdata["node_list"]: + nodename = _get_base_node_name(node, tfdata) + + # Skip certain resource types + if _should_skip_node(node, nodename): + continue + + # Get metadata generator for parameter scanning + dg = _get_metadata_generator(node, nodename, tfdata) + + # Check each parameter for relationships + for param_item_list in dg: + matching_result = check_relationship(node, param_item_list, tfdata) + # Process connection pairs + if matching_result and len(matching_result) >= 2: + tfdata = _process_connection_pairs(matching_result, tfdata) + + return tfdata + + +def _remove_hidden_nodes(tfdata: Dict[str, Any]) -> Dict[str, Any]: + """Remove hidden nodes from graph. + + Returns mutated tfdata. + """ + # Delete hidden resource nodes + for hidden_resource in tfdata["hidden"]: + if hidden_resource in tfdata["graphdict"]: + del tfdata["graphdict"][hidden_resource] + # Remove hidden resources from connection lists + for resource in tfdata["graphdict"]: + for hidden_resource in tfdata["hidden"]: + if hidden_resource in tfdata["graphdict"][resource]: + tfdata["graphdict"][resource].remove(hidden_resource) + + return tfdata + + def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: - """Build final graph structure by detecting resource relationships. + """Build final graph structure by detecting ALL resource relationships. - Scans resource metadata to find references between resources and adds + Scans resource metadata to find cross references between resources/modules and adds connections to the graph. Handles hidden nodes and security groups specially. Args: @@ -461,8 +563,9 @@ def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: Returns: Updated tfdata with complete graphdict including all relationships """ - # Deep copy to prevent mutation leakage - graphdict = copy.deepcopy(tfdata["graphdict"]) + # Deep copy graphdict to prevent mutation issues during iteration + tfdata["graphdict"] = copy.deepcopy(tfdata["graphdict"]) + created_resources = len(tfdata["node_list"]) click.echo( click.style( @@ -473,75 +576,16 @@ def add_relations(tfdata: Dict[str, Any]) -> Dict[str, Any]: ) # Scan each node for relationships - for node in tfdata["node_list"]: - # Determine base node name - if node not in tfdata["meta_data"].keys(): - nodename = node.split("~")[0] - if "[" in nodename: - nodename = nodename.split("[")[0] - else: - nodename = node - - # Skip certain resource types - if ( - helpers.get_no_module_name(nodename).startswith("random") - or helpers.get_no_module_name(node).startswith("aws_security_group") - or helpers.get_no_module_name(node).startswith("null") - ): - continue - - # Get metadata generator for parameter scanning - if nodename not in tfdata["meta_data"].keys(): - if node in tfdata["original_metadata"]: - dg = dict_generator(tfdata["original_metadata"][node]) - tfdata["meta_data"][node] = copy.deepcopy( - tfdata["original_metadata"][node] - ) - else: - dg = dict_generator(tfdata["meta_data"][nodename]) - - # Check each parameter for relationships - for param_item_list in dg: - matching_result = check_relationship( - node, - param_item_list, - tfdata, - ) - # Process connection pairs - if matching_result and len(matching_result) >= 2: - for i in range(0, len(matching_result), 2): - origin = matching_result[i] - dest = matching_result[i + 1] - c_list = list(graphdict[origin]) - # Add connection if not exists and not security group - if dest not in c_list and not helpers.get_no_module_name( - origin - ).startswith("aws_security_group"): - click.echo(f" {origin} --> {dest}") - c_list.append(dest) - # Replace unnumbered with numbered version - if ( - "~" in origin - and "~" in dest - and dest.split("~")[0] in c_list - ): - c_list.remove(dest.split("~")[0]) - graphdict[origin] = c_list + tfdata = _scan_node_relationships(tfdata) # Remove hidden nodes from graph - for hidden_resource in tfdata["hidden"]: - del graphdict[hidden_resource] - for resource in graphdict: - for hidden_resource in tfdata["hidden"]: - if hidden_resource in graphdict[resource]: - graphdict[resource].remove(hidden_resource) + tfdata = _remove_hidden_nodes(tfdata) # Scan module-to-module relationships - scan_module_relationships(tfdata, graphdict) + scan_module_relationships(tfdata, tfdata["graphdict"]) - tfdata["graphdict"] = graphdict # Store immutable snapshot for reference - tfdata["original_graphdict_with_relations"] = copy.deepcopy(graphdict) + tfdata["original_graphdict_with_relations"] = copy.deepcopy(tfdata["graphdict"]) return tfdata From 4f123fa69b6f6157eb313011c3bd429114b5963e Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 09:19:21 +0000 Subject: [PATCH 5/8] GVPR title fix --- modules/config/cloud_config_aws.py | 6 ++++++ shiftLabel.gvpr | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/modules/config/cloud_config_aws.py b/modules/config/cloud_config_aws.py index 367b02a..9de745e 100644 --- a/modules/config/cloud_config_aws.py +++ b/modules/config/cloud_config_aws.py @@ -141,6 +141,12 @@ # List of prefixes where additional nodes should be created automatically AWS_AUTO_ANNOTATIONS = [ {"aws_route53": {"link": ["tv_aws_users.users"], "arrow": "reverse"}}, + { + "aws_cloudfront_distribution": { + "link": ["tv_aws_users.users"], + "arrow": "reverse", + } + }, { "aws_dx": { "link": [ diff --git a/shiftLabel.gvpr b/shiftLabel.gvpr index b4d0a91..5793fd2 100644 --- a/shiftLabel.gvpr +++ b/shiftLabel.gvpr @@ -2,6 +2,7 @@ BEGIN{ double bbMinX, bbMinY, bbMaxX, bbMaxY, lpX, lpY, lpMinX, lpMaxY, newX, newY, centerX; double fudgeX, fudgeY; double cloudMinX, cloudMinY, cloudMaxX, cloudMaxY, cloudCenterX; + double topMostY; string fld[int]; // recursive routine, processing from the top (root) down @@ -42,7 +43,19 @@ BEGIN{ } // end of labelShift } BEG_G{ + node_t n; + double nodeY; + topMostY = cloudMaxY; + labelShift($G); + + // Find topmost node position + for (n = fstnode($G); n; n = nxtnode(n)) { + if (hasAttr(n, "_titlenode") && n._titlenode == "1") continue; + if (hasAttr(n, "_footernode") && n._footernode == "1") continue; + nodeY = yOf(n.pos); + if (nodeY > topMostY) topMostY = nodeY; + } } END_G{ double gbbMinX, gbbMinY, gbbMaxX, gbbMaxY, gcenterX, glpY; @@ -53,7 +66,7 @@ END_G{ $G.lp = sprintf("%.1f,%.1f", gcenterX, glpY); } N[_titlenode=="1"]{ - pos=sprintf("%.0f,%.0f!", cloudCenterX, cloudMaxY + 100); + pos=sprintf("%.0f,%.0f!", cloudCenterX, topMostY + 200); } N[_footernode=="1"]{ pos=sprintf("%.0f,%.0f!", cloudCenterX, cloudMinY - 150); From d8dde40d6f11f26ec602f3fead26ca90ed6222c7 Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 09:22:39 +0000 Subject: [PATCH 6/8] added new static website test for cross-module references --- tests/integration_test.py | 1 + tests/json/expected-static-website.json | 13 + tests/json/static-website-tfdata.json | 8419 +++++++++++++++++++++++ 3 files changed, 8433 insertions(+) create mode 100644 tests/json/expected-static-website.json create mode 100644 tests/json/static-website-tfdata.json diff --git a/tests/integration_test.py b/tests/integration_test.py index 3b2c70f..a804a8a 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -53,6 +53,7 @@ def test_help() -> None: ("wordpress-tfdata.json", "expected-wordpress.json"), ("bastion-tfdata.json", "bastion-expected.json"), ("eks-basic-tfdata.json", "expected-eks-basic.json"), + ("static-website-tfdata.json", "expected-static-website.json"), ], ) def test_graphdata_output(json_path: str, expected_file: str, tmp_path: Path) -> None: diff --git a/tests/json/expected-static-website.json b/tests/json/expected-static-website.json new file mode 100644 index 0000000..8a3a1db --- /dev/null +++ b/tests/json/expected-static-website.json @@ -0,0 +1,13 @@ +{ + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": [ + "module.s3_bucket.aws_s3_bucket.this[0]~1" + ], + "module.s3_bucket.aws_s3_bucket.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": [], + "tv_aws_users.users": [ + "module.cloudfront.aws_cloudfront_distribution.this[0]~1" + ] +} \ No newline at end of file diff --git a/tests/json/static-website-tfdata.json b/tests/json/static-website-tfdata.json new file mode 100644 index 0000000..3aa8276 --- /dev/null +++ b/tests/json/static-website-tfdata.json @@ -0,0 +1,8419 @@ +{ + "codepath": "/Users/patrick/git/terravision/tests/fixtures/aws_terraform/static-website", + "workdir": "/Users/patrick/git/terravision", + "plandata": { + "format_version": "1.2", + "terraform_version": "1.13.3", + "variables": { + "aws_region": { + "value": "us-east-1" + }, + "bucket_name": { + "value": "my-react-static-website" + } + }, + "planned_values": { + "outputs": { + "cloudfront_distribution_domain_name": { + "sensitive": false + }, + "s3_bucket_name": { + "sensitive": false + }, + "website_url": { + "sensitive": false + } + }, + "root_module": { + "child_modules": [ + { + "resources": [ + { + "address": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "mode": "managed", + "type": "aws_cloudfront_distribution", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "aliases": null, + "comment": "CloudFront distribution for my-react-static-website", + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + "GET", + "HEAD" + ], + "cache_policy_id": null, + "cached_methods": [ + "GET", + "HEAD" + ], + "compress": true, + "field_level_encryption_id": null, + "forwarded_values": [ + { + "cookies": [ + { + "forward": "none" + } + ], + "query_string": false, + "query_string_cache_keys": [] + } + ], + "function_association": [], + "lambda_function_association": [], + "min_ttl": 0, + "origin_request_policy_id": null, + "realtime_log_config_arn": null, + "response_headers_policy_id": null, + "smooth_streaming": null, + "target_origin_id": "S3-my-react-static-website", + "viewer_protocol_policy": "redirect-to-https" + } + ], + "default_root_object": "index.html", + "enabled": true, + "http_version": "http2", + "is_ipv6_enabled": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "connection_attempts": 3, + "connection_timeout": 10, + "custom_header": [], + "custom_origin_config": [], + "origin_access_control_id": "", + "origin_id": "S3-my-react-static-website", + "origin_path": "", + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "price_class": "PriceClass_100", + "restrictions": [ + { + "geo_restriction": [ + { + "restriction_type": "none" + } + ] + } + ], + "retain_on_delete": false, + "staging": false, + "tags": null, + "viewer_certificate": [ + { + "acm_certificate_arn": null, + "cloudfront_default_certificate": true, + "iam_certificate_id": null, + "minimum_protocol_version": "TLSv1", + "ssl_support_method": null + } + ], + "wait_for_deployment": true, + "web_acl_id": null + }, + "sensitive_values": { + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "viewer_certificate": [ + {} + ] + } + } + ], + "address": "module.cloudfront" + }, + { + "resources": [ + { + "address": "module.s3_bucket.aws_s3_bucket.this[0]", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "my-react-static-website", + "force_destroy": false, + "object_lock_enabled": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_acl.this[0]", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acl": "private", + "expected_bucket_owner": null + }, + "sensitive_values": { + "access_control_policy": [] + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "sensitive_values": {} + }, + { + "address": "module.s3_bucket.aws_s3_bucket_versioning.this[0]", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]", + "mode": "managed", + "type": "aws_s3_bucket_website_configuration", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "error_document": [ + { + "key": "error.html" + } + ], + "expected_bucket_owner": null, + "index_document": [ + { + "suffix": "index.html" + } + ], + "redirect_all_requests_to": [] + }, + "sensitive_values": { + "error_document": [ + {} + ], + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "routing_rule": [] + } + } + ], + "address": "module.s3_bucket" + } + ] + } + }, + "resource_changes": [ + { + "address": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "module_address": "module.cloudfront", + "mode": "managed", + "type": "aws_cloudfront_distribution", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "aliases": null, + "comment": "CloudFront distribution for my-react-static-website", + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "default_root_object": "index.html", + "enabled": true, + "http_version": "http2", + "is_ipv6_enabled": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "price_class": "PriceClass_100", + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "retain_on_delete": false, + "staging": false, + "tags": null, + "viewer_certificate": [ + {} + ], + "wait_for_deployment": true, + "web_acl_id": null, + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "status": true, + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "module": "cloudfront" + }, + "after_unknown": { + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "default_ttl": true, + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": true + } + ], + "headers": true, + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": true, + "lambda_function_association": [], + "max_ttl": true, + "trusted_key_groups": true, + "trusted_signers": true + } + ], + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "domain_name": true, + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "restrictions": [ + { + "geo_restriction": [ + { + "locations": true + } + ] + } + ], + "status": true, + "tags_all": true, + "trusted_key_groups": true, + "trusted_signers": true, + "viewer_certificate": [ + {} + ] + }, + "before_sensitive": false, + "after_sensitive": { + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "viewer_certificate": [ + {} + ] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "my-react-static-website", + "force_destroy": false, + "object_lock_enabled": false, + "tags": null, + "timeouts": null, + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": [], + "grant": [], + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "policy": true, + "region": true, + "replication_configuration": [], + "request_payer": true, + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [], + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_acl.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "private", + "expected_bucket_owner": null, + "access_control_policy": [], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false, + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_versioning.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + {} + ], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_website_configuration", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "error_document": [ + {} + ], + "expected_bucket_owner": null, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "bucket": true, + "id": true, + "routing_rule": [], + "routing_rules": true, + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "error_document": [ + {} + ], + "id": true, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "routing_rule": true, + "routing_rules": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "error_document": [ + {} + ], + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "routing_rule": [] + } + } + } + ], + "output_changes": { + "cloudfront_distribution_domain_name": { + "actions": [ + "create" + ], + "before": null, + "after_unknown": true, + "before_sensitive": false, + "after_sensitive": false + }, + "s3_bucket_name": { + "actions": [ + "create" + ], + "before": null, + "after_unknown": true, + "before_sensitive": false, + "after_sensitive": false + }, + "website_url": { + "actions": [ + "create" + ], + "before": null, + "after_unknown": true, + "before_sensitive": false, + "after_sensitive": false + } + }, + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.13.3", + "values": { + "root_module": { + "child_modules": [ + { + "resources": [ + { + "address": "module.s3_bucket.data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "account_id": "088594415319", + "arn": "arn:aws:sts::088594415319:assumed-role/AWSReservedSSO_AdministratorAccess_f85892d5b99976fd/patrickchugh", + "id": "088594415319", + "user_id": "AROARJIFDP3LWVCWLZW2K:patrickchugh" + }, + "sensitive_values": {} + }, + { + "address": "module.s3_bucket.data.aws_canonical_user_id.this[0]", + "mode": "data", + "type": "aws_canonical_user_id", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "display_name": "", + "id": "f2b43c604376a5810dcf6ae6ae6338ac13843a72c2d7392ca4c7469e530b5df0" + }, + "sensitive_values": {} + }, + { + "address": "module.s3_bucket.data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "dns_suffix": "amazonaws.com", + "id": "aws", + "partition": "aws", + "reverse_dns_prefix": "com.amazonaws" + }, + "sensitive_values": {} + }, + { + "address": "module.s3_bucket.data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "US East (N. Virginia)", + "endpoint": "ec2.us-east-1.amazonaws.com", + "id": "us-east-1", + "name": "us-east-1" + }, + "sensitive_values": {} + } + ], + "address": "module.s3_bucket" + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 5.0", + "expressions": { + "region": { + "references": [ + "var.aws_region" + ] + } + } + } + }, + "root_module": { + "outputs": { + "cloudfront_distribution_domain_name": { + "expression": { + "references": [ + "module.cloudfront.cloudfront_distribution_domain_name", + "module.cloudfront" + ] + }, + "description": "CloudFront distribution domain name" + }, + "s3_bucket_name": { + "expression": { + "references": [ + "module.s3_bucket.s3_bucket_id", + "module.s3_bucket" + ] + }, + "description": "S3 bucket name" + }, + "website_url": { + "expression": { + "references": [ + "module.cloudfront.cloudfront_distribution_domain_name", + "module.cloudfront" + ] + }, + "description": "Website URL" + } + }, + "module_calls": { + "cloudfront": { + "source": "terraform-aws-modules/cloudfront/aws", + "expressions": { + "comment": { + "references": [ + "var.bucket_name" + ] + }, + "default_cache_behavior": { + "references": [ + "var.bucket_name" + ] + }, + "default_root_object": { + "constant_value": "index.html" + }, + "enabled": { + "constant_value": true + }, + "is_ipv6_enabled": { + "constant_value": true + }, + "origin": { + "references": [ + "module.s3_bucket.s3_bucket_bucket_regional_domain_name", + "module.s3_bucket", + "var.bucket_name" + ] + }, + "price_class": { + "constant_value": "PriceClass_100" + }, + "viewer_certificate": { + "constant_value": { + "cloudfront_default_certificate": true + } + } + }, + "module": { + "outputs": { + "cloudfront_distribution_arn": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].arn", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The ARN (Amazon Resource Name) for the distribution." + }, + "cloudfront_distribution_caller_reference": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].caller_reference", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "Internal value used by CloudFront to allow future updates to the distribution configuration." + }, + "cloudfront_distribution_domain_name": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].domain_name", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The domain name corresponding to the distribution." + }, + "cloudfront_distribution_etag": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].etag", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The current version of the distribution's information." + }, + "cloudfront_distribution_hosted_zone_id": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].hosted_zone_id", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The CloudFront Route 53 zone ID that can be used to route an Alias Resource Record Set to." + }, + "cloudfront_distribution_id": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].id", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The identifier for the distribution." + }, + "cloudfront_distribution_in_progress_validation_batches": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].in_progress_validation_batches", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The number of invalidation batches currently in progress." + }, + "cloudfront_distribution_last_modified_time": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].last_modified_time", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The date and time the distribution was last modified." + }, + "cloudfront_distribution_status": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].status", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "The current status of the distribution. Deployed if the distribution's information is fully propagated throughout the Amazon CloudFront system." + }, + "cloudfront_distribution_tags": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].tags_all", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "Tags of the distribution's" + }, + "cloudfront_distribution_trusted_signers": { + "expression": { + "references": [ + "aws_cloudfront_distribution.this[0].trusted_signers", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "description": "List of nested attributes for active trusted signers, if the distribution is set up to serve private content with signed URLs" + }, + "cloudfront_monitoring_subscription_id": { + "expression": { + "references": [ + "aws_cloudfront_monitoring_subscription.this[0].id", + "aws_cloudfront_monitoring_subscription.this[0]", + "aws_cloudfront_monitoring_subscription.this" + ] + }, + "description": " The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`." + }, + "cloudfront_origin_access_controls": { + "expression": { + "references": [ + "local.create_origin_access_control", + "aws_cloudfront_origin_access_control.this" + ] + }, + "description": "The origin access controls created" + }, + "cloudfront_origin_access_controls_ids": { + "expression": { + "references": [ + "local.create_origin_access_control", + "aws_cloudfront_origin_access_control.this" + ] + }, + "description": "The IDS of the origin access identities created" + }, + "cloudfront_origin_access_identities": { + "expression": { + "references": [ + "aws_cloudfront_origin_access_identity.this", + "local.create_origin_access_identity" + ] + }, + "description": "The origin access identities created" + }, + "cloudfront_origin_access_identity_iam_arns": { + "expression": { + "references": [ + "aws_cloudfront_origin_access_identity.this", + "local.create_origin_access_identity" + ] + }, + "description": "The IAM arns of the origin access identities created" + }, + "cloudfront_origin_access_identity_ids": { + "expression": { + "references": [ + "aws_cloudfront_origin_access_identity.this", + "local.create_origin_access_identity" + ] + }, + "description": "The IDS of the origin access identities created" + } + }, + "resources": [ + { + "address": "aws_cloudfront_distribution.this", + "mode": "managed", + "type": "aws_cloudfront_distribution", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "aliases": { + "references": [ + "var.aliases" + ] + }, + "comment": { + "references": [ + "var.comment" + ] + }, + "continuous_deployment_policy_id": { + "references": [ + "var.continuous_deployment_policy_id" + ] + }, + "default_root_object": { + "references": [ + "var.default_root_object" + ] + }, + "enabled": { + "references": [ + "var.enabled" + ] + }, + "http_version": { + "references": [ + "var.http_version" + ] + }, + "is_ipv6_enabled": { + "references": [ + "var.is_ipv6_enabled" + ] + }, + "price_class": { + "references": [ + "var.price_class" + ] + }, + "restrictions": [ + {} + ], + "retain_on_delete": { + "references": [ + "var.retain_on_delete" + ] + }, + "staging": { + "references": [ + "var.staging" + ] + }, + "tags": { + "references": [ + "var.tags" + ] + }, + "viewer_certificate": [ + { + "acm_certificate_arn": { + "references": [ + "var.viewer_certificate" + ] + }, + "cloudfront_default_certificate": { + "references": [ + "var.viewer_certificate" + ] + }, + "iam_certificate_id": { + "references": [ + "var.viewer_certificate" + ] + }, + "minimum_protocol_version": { + "references": [ + "var.viewer_certificate" + ] + }, + "ssl_support_method": { + "references": [ + "var.viewer_certificate" + ] + } + } + ], + "wait_for_deployment": { + "references": [ + "var.wait_for_deployment" + ] + }, + "web_acl_id": { + "references": [ + "var.web_acl_id" + ] + } + }, + "schema_version": 1, + "count_expression": { + "references": [ + "var.create_distribution" + ] + } + }, + { + "address": "aws_cloudfront_monitoring_subscription.this", + "mode": "managed", + "type": "aws_cloudfront_monitoring_subscription", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "distribution_id": { + "references": [ + "aws_cloudfront_distribution.this[0].id", + "aws_cloudfront_distribution.this[0]", + "aws_cloudfront_distribution.this" + ] + }, + "monitoring_subscription": [ + { + "realtime_metrics_subscription_config": [ + { + "realtime_metrics_subscription_status": { + "references": [ + "var.realtime_metrics_subscription_status" + ] + } + } + ] + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "var.create_distribution", + "var.create_monitoring_subscription" + ] + } + }, + { + "address": "aws_cloudfront_origin_access_control.this", + "mode": "managed", + "type": "aws_cloudfront_origin_access_control", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "description": { + "references": [ + "each.value[\"description\"]", + "each.value" + ] + }, + "name": { + "references": [ + "each.key" + ] + }, + "origin_access_control_origin_type": { + "references": [ + "each.value[\"origin_type\"]", + "each.value" + ] + }, + "signing_behavior": { + "references": [ + "each.value[\"signing_behavior\"]", + "each.value" + ] + }, + "signing_protocol": { + "references": [ + "each.value[\"signing_protocol\"]", + "each.value" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "local.create_origin_access_control", + "var.origin_access_control" + ] + } + }, + { + "address": "aws_cloudfront_origin_access_identity.this", + "mode": "managed", + "type": "aws_cloudfront_origin_access_identity", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "comment": { + "references": [ + "each.value" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "local.create_origin_access_identity", + "var.origin_access_identities" + ] + } + }, + { + "address": "data.aws_cloudfront_cache_policy.this", + "mode": "data", + "type": "aws_cloudfront_cache_policy", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "name": { + "references": [ + "each.key" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "var.default_cache_behavior", + "var.ordered_cache_behavior" + ] + } + }, + { + "address": "data.aws_cloudfront_origin_request_policy.this", + "mode": "data", + "type": "aws_cloudfront_origin_request_policy", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "name": { + "references": [ + "each.key" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "var.default_cache_behavior", + "var.ordered_cache_behavior" + ] + } + }, + { + "address": "data.aws_cloudfront_response_headers_policy.this", + "mode": "data", + "type": "aws_cloudfront_response_headers_policy", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "name": { + "references": [ + "each.key" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "var.default_cache_behavior", + "var.ordered_cache_behavior" + ] + } + } + ], + "variables": { + "aliases": { + "default": null, + "description": "Extra CNAMEs (alternate domain names), if any, for this distribution." + }, + "comment": { + "default": null, + "description": "Any comments you want to include about the distribution." + }, + "continuous_deployment_policy_id": { + "default": null, + "description": "Identifier of a continuous deployment policy. This argument should only be set on a production distribution." + }, + "create_distribution": { + "default": true, + "description": "Controls if CloudFront distribution should be created" + }, + "create_monitoring_subscription": { + "default": false, + "description": "If enabled, the resource for monitoring subscription will created." + }, + "create_origin_access_control": { + "default": false, + "description": "Controls if CloudFront origin access control should be created" + }, + "create_origin_access_identity": { + "default": false, + "description": "Controls if CloudFront origin access identity should be created" + }, + "custom_error_response": { + "default": {}, + "description": "One or more custom error response elements" + }, + "default_cache_behavior": { + "default": null, + "description": "The default cache behavior for this distribution" + }, + "default_root_object": { + "default": null, + "description": "The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL." + }, + "enabled": { + "default": true, + "description": "Whether the distribution is enabled to accept end user requests for content." + }, + "geo_restriction": { + "default": {}, + "description": "The restriction configuration for this distribution (geo_restrictions)" + }, + "http_version": { + "default": "http2", + "description": "The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3, and http3. The default is http2." + }, + "is_ipv6_enabled": { + "default": null, + "description": "Whether the IPv6 is enabled for the distribution." + }, + "logging_config": { + "default": {}, + "description": "The logging configuration that controls how logs are written to your distribution (maximum one)." + }, + "ordered_cache_behavior": { + "default": [], + "description": "An ordered list of cache behaviors resource for this distribution. List from top to bottom in order of precedence. The topmost cache behavior will have precedence 0." + }, + "origin": { + "default": null, + "description": "One or more origins for this distribution (multiples allowed)." + }, + "origin_access_control": { + "default": { + "s3": { + "description": "", + "origin_type": "s3", + "signing_behavior": "always", + "signing_protocol": "sigv4" + } + }, + "description": "Map of CloudFront origin access control" + }, + "origin_access_identities": { + "default": {}, + "description": "Map of CloudFront origin access identities (value as a comment)" + }, + "origin_group": { + "default": {}, + "description": "One or more origin_group for this distribution (multiples allowed)." + }, + "price_class": { + "default": null, + "description": "The price class for this distribution. One of PriceClass_All, PriceClass_200, PriceClass_100" + }, + "realtime_metrics_subscription_status": { + "default": "Enabled", + "description": "A flag that indicates whether additional CloudWatch metrics are enabled for a given CloudFront distribution. Valid values are `Enabled` and `Disabled`." + }, + "retain_on_delete": { + "default": false, + "description": "Disables the distribution instead of deleting it when destroying the resource through Terraform. If this is set, the distribution needs to be deleted manually afterwards." + }, + "staging": { + "default": false, + "description": "Whether the distribution is a staging distribution." + }, + "tags": { + "default": null, + "description": "A map of tags to assign to the resource." + }, + "viewer_certificate": { + "default": { + "cloudfront_default_certificate": true, + "minimum_protocol_version": "TLSv1" + }, + "description": "The SSL configuration for this distribution" + }, + "wait_for_deployment": { + "default": true, + "description": "If enabled, the resource will wait for the distribution status to change from InProgress to Deployed. Setting this to false will skip the process." + }, + "web_acl_id": { + "default": null, + "description": "If you're using AWS WAF to filter CloudFront requests, the Id of the AWS WAF web ACL that is associated with the distribution. The WAF Web ACL must exist in the WAF Global (CloudFront) region and the credentials configuring this argument must have waf:GetWebACL permissions assigned. If using WAFv2, provide the ARN of the web ACL." + } + } + }, + "version_constraint": "~> 3.0" + }, + "s3_bucket": { + "source": "terraform-aws-modules/s3-bucket/aws", + "expressions": { + "acl": { + "constant_value": "private" + }, + "block_public_acls": { + "constant_value": false + }, + "block_public_policy": { + "constant_value": false + }, + "bucket": { + "references": [ + "var.bucket_name" + ] + }, + "ignore_public_acls": { + "constant_value": false + }, + "restrict_public_buckets": { + "constant_value": false + }, + "versioning": { + "constant_value": { + "enabled": true + } + }, + "website": { + "constant_value": { + "error_document": "error.html", + "index_document": "index.html" + } + } + }, + "module": { + "outputs": { + "s3_bucket_arn": { + "expression": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The ARN of the bucket. Will be of format arn:aws:s3:::bucketname." + }, + "s3_bucket_bucket_domain_name": { + "expression": { + "references": [ + "aws_s3_bucket.this[0].bucket_domain_name", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The bucket domain name. Will be of format bucketname.s3.amazonaws.com." + }, + "s3_bucket_bucket_regional_domain_name": { + "expression": { + "references": [ + "aws_s3_bucket.this[0].bucket_regional_domain_name", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL." + }, + "s3_bucket_hosted_zone_id": { + "expression": { + "references": [ + "aws_s3_bucket.this[0].hosted_zone_id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The Route 53 Hosted Zone ID for this bucket's region." + }, + "s3_bucket_id": { + "expression": { + "references": [ + "aws_s3_bucket_policy.this[0].id", + "aws_s3_bucket_policy.this[0]", + "aws_s3_bucket_policy.this", + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The name of the bucket." + }, + "s3_bucket_lifecycle_configuration_rules": { + "expression": { + "references": [ + "aws_s3_bucket_lifecycle_configuration.this[0].rule", + "aws_s3_bucket_lifecycle_configuration.this[0]", + "aws_s3_bucket_lifecycle_configuration.this" + ] + }, + "description": "The lifecycle rules of the bucket, if the bucket is configured with lifecycle rules. If not, this will be an empty string." + }, + "s3_bucket_policy": { + "expression": { + "references": [ + "aws_s3_bucket_policy.this[0].policy", + "aws_s3_bucket_policy.this[0]", + "aws_s3_bucket_policy.this" + ] + }, + "description": "The policy of the bucket, if the bucket is configured with a policy. If not, this will be an empty string." + }, + "s3_bucket_region": { + "expression": { + "references": [ + "aws_s3_bucket.this[0].region", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "description": "The AWS region this bucket resides in." + }, + "s3_bucket_website_domain": { + "expression": { + "references": [ + "aws_s3_bucket_website_configuration.this[0].website_domain", + "aws_s3_bucket_website_configuration.this[0]", + "aws_s3_bucket_website_configuration.this" + ] + }, + "description": "The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records." + }, + "s3_bucket_website_endpoint": { + "expression": { + "references": [ + "aws_s3_bucket_website_configuration.this[0].website_endpoint", + "aws_s3_bucket_website_configuration.this[0]", + "aws_s3_bucket_website_configuration.this" + ] + }, + "description": "The website endpoint, if the bucket is configured with a website. If not, this will be an empty string." + } + }, + "resources": [ + { + "address": "aws_s3_bucket.this", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "var.bucket" + ] + }, + "bucket_prefix": { + "references": [ + "var.bucket_prefix" + ] + }, + "force_destroy": { + "references": [ + "var.force_destroy" + ] + }, + "object_lock_enabled": { + "references": [ + "var.object_lock_enabled" + ] + }, + "tags": { + "references": [ + "var.tags" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket" + ] + } + }, + { + "address": "aws_s3_bucket_accelerate_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_accelerate_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + }, + "status": { + "references": [ + "var.acceleration_status" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.acceleration_status" + ] + } + }, + { + "address": "aws_s3_bucket_acl.this", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "acl": { + "references": [ + "var.acl", + "var.acl" + ] + }, + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "local.create_bucket_acl" + ] + }, + "depends_on": [ + "aws_s3_bucket_ownership_controls.this" + ] + }, + { + "address": "aws_s3_bucket_analytics_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_analytics_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "name": { + "references": [ + "each.key" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "var.analytics_configuration", + "local.create_bucket" + ] + } + }, + { + "address": "aws_s3_bucket_cors_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_cors_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "local.cors_rules" + ] + } + }, + { + "address": "aws_s3_bucket_intelligent_tiering_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_intelligent_tiering_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "name": { + "references": [ + "each.key" + ] + }, + "status": { + "references": [ + "each.value.status", + "each.value", + "each.value.status", + "each.value" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "local.intelligent_tiering", + "local.create_bucket" + ] + } + }, + { + "address": "aws_s3_bucket_inventory.this", + "mode": "managed", + "type": "aws_s3_bucket_inventory", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "each.value.bucket", + "each.value", + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "destination": [ + { + "bucket": [ + { + "account_id": { + "references": [ + "each.value.destination.account_id", + "each.value.destination", + "each.value" + ] + }, + "bucket_arn": { + "references": [ + "each.value.destination.bucket_arn", + "each.value.destination", + "each.value", + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "format": { + "references": [ + "each.value.destination.format", + "each.value.destination", + "each.value" + ] + }, + "prefix": { + "references": [ + "each.value.destination.prefix", + "each.value.destination", + "each.value" + ] + } + } + ] + } + ], + "enabled": { + "references": [ + "each.value.enabled", + "each.value" + ] + }, + "included_object_versions": { + "references": [ + "each.value.included_object_versions", + "each.value" + ] + }, + "name": { + "references": [ + "each.key" + ] + }, + "optional_fields": { + "references": [ + "each.value.optional_fields", + "each.value" + ] + }, + "schedule": [ + { + "frequency": { + "references": [ + "each.value.frequency", + "each.value" + ] + } + } + ] + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "var.inventory_configuration", + "local.create_bucket" + ] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + } + }, + "schema_version": 1, + "count_expression": { + "references": [ + "local.create_bucket", + "local.lifecycle_rules" + ] + }, + "depends_on": [ + "aws_s3_bucket_versioning.this" + ] + }, + { + "address": "aws_s3_bucket_logging.this", + "mode": "managed", + "type": "aws_s3_bucket_logging", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "target_bucket": { + "references": [ + "var.logging[\"target_bucket\"]", + "var.logging" + ] + }, + "target_prefix": { + "references": [ + "var.logging[\"target_prefix\"]", + "var.logging" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.logging" + ] + } + }, + { + "address": "aws_s3_bucket_metric.this", + "mode": "managed", + "type": "aws_s3_bucket_metric", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "name": { + "references": [ + "each.value.name", + "each.value" + ] + } + }, + "schema_version": 0, + "for_each_expression": { + "references": [ + "local.metric_configuration", + "local.create_bucket" + ] + } + }, + { + "address": "aws_s3_bucket_object_lock_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_object_lock_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + }, + "rule": [ + { + "default_retention": [ + { + "days": { + "references": [ + "var.object_lock_configuration.rule.default_retention.days", + "var.object_lock_configuration.rule.default_retention", + "var.object_lock_configuration.rule", + "var.object_lock_configuration" + ] + }, + "mode": { + "references": [ + "var.object_lock_configuration.rule.default_retention.mode", + "var.object_lock_configuration.rule.default_retention", + "var.object_lock_configuration.rule", + "var.object_lock_configuration" + ] + }, + "years": { + "references": [ + "var.object_lock_configuration.rule.default_retention.years", + "var.object_lock_configuration.rule.default_retention", + "var.object_lock_configuration.rule", + "var.object_lock_configuration" + ] + } + } + ] + } + ], + "token": { + "references": [ + "var.object_lock_configuration.token", + "var.object_lock_configuration" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.object_lock_enabled", + "var.object_lock_configuration.rule.default_retention", + "var.object_lock_configuration.rule", + "var.object_lock_configuration" + ] + } + }, + { + "address": "aws_s3_bucket_ownership_controls.this", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "local.attach_policy", + "aws_s3_bucket_policy.this[0].id", + "aws_s3_bucket_policy.this[0]", + "aws_s3_bucket_policy.this", + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "rule": [ + { + "object_ownership": { + "references": [ + "var.object_ownership" + ] + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.control_object_ownership" + ] + }, + "depends_on": [ + "aws_s3_bucket_policy.this", + "aws_s3_bucket_public_access_block.this", + "aws_s3_bucket.this" + ] + }, + { + "address": "aws_s3_bucket_policy.this", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.combined[0].json", + "data.aws_iam_policy_document.combined[0]", + "data.aws_iam_policy_document.combined" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "local.attach_policy" + ] + }, + "depends_on": [ + "aws_s3_bucket_public_access_block.this" + ] + }, + { + "address": "aws_s3_bucket_public_access_block.this", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "references": [ + "var.block_public_acls" + ] + }, + "block_public_policy": { + "references": [ + "var.block_public_policy" + ] + }, + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "ignore_public_acls": { + "references": [ + "var.ignore_public_acls" + ] + }, + "restrict_public_buckets": { + "references": [ + "var.restrict_public_buckets" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_public_policy" + ] + } + }, + { + "address": "aws_s3_bucket_replication_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "role": { + "references": [ + "var.replication_configuration[\"role\"]", + "var.replication_configuration" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.replication_configuration" + ] + }, + "depends_on": [ + "aws_s3_bucket_versioning.this" + ] + }, + { + "address": "aws_s3_bucket_request_payment_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_request_payment_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + }, + "payer": { + "references": [ + "var.request_payer" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.request_payer" + ] + } + }, + { + "address": "aws_s3_bucket_server_side_encryption_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.server_side_encryption_configuration" + ] + } + }, + { + "address": "aws_s3_bucket_versioning.this", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + }, + "mfa": { + "references": [ + "var.versioning[\"mfa\"]", + "var.versioning" + ] + }, + "versioning_configuration": [ + { + "mfa_delete": { + "references": [ + "var.versioning[\"mfa_delete\"]", + "var.versioning", + "var.versioning[\"mfa_delete\"]", + "var.versioning" + ] + }, + "status": { + "references": [ + "var.versioning[\"enabled\"]", + "var.versioning", + "var.versioning[\"status\"]", + "var.versioning", + "var.versioning[\"status\"]", + "var.versioning" + ] + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.versioning" + ] + } + }, + { + "address": "aws_s3_bucket_website_configuration.this", + "mode": "managed", + "type": "aws_s3_bucket_website_configuration", + "name": "this", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.this[0].id", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "expected_bucket_owner": { + "references": [ + "var.expected_bucket_owner" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.website" + ] + } + }, + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_canonical_user_id.this", + "mode": "data", + "type": "aws_canonical_user_id", + "name": "this", + "provider_config_key": "aws", + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "local.create_bucket_acl", + "var.owner[\"id\"]", + "var.owner" + ] + } + }, + { + "address": "data.aws_iam_policy_document.access_log_delivery", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "access_log_delivery", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "logging.s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "AWSAccessLogDeliveryWrite" + } + }, + { + "actions": { + "constant_value": [ + "s3:GetBucketAcl" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "logging.s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "AWSAccessLogDeliveryAclCheck" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_access_log_delivery_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.combined", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "combined", + "provider_config_key": "aws", + "expressions": { + "source_policy_documents": { + "references": [ + "var.attach_elb_log_delivery_policy", + "data.aws_iam_policy_document.elb_log_delivery[0].json", + "data.aws_iam_policy_document.elb_log_delivery[0]", + "data.aws_iam_policy_document.elb_log_delivery", + "var.attach_lb_log_delivery_policy", + "data.aws_iam_policy_document.lb_log_delivery[0].json", + "data.aws_iam_policy_document.lb_log_delivery[0]", + "data.aws_iam_policy_document.lb_log_delivery", + "var.attach_access_log_delivery_policy", + "data.aws_iam_policy_document.access_log_delivery[0].json", + "data.aws_iam_policy_document.access_log_delivery[0]", + "data.aws_iam_policy_document.access_log_delivery", + "var.attach_require_latest_tls_policy", + "data.aws_iam_policy_document.require_latest_tls[0].json", + "data.aws_iam_policy_document.require_latest_tls[0]", + "data.aws_iam_policy_document.require_latest_tls", + "var.attach_deny_insecure_transport_policy", + "data.aws_iam_policy_document.deny_insecure_transport[0].json", + "data.aws_iam_policy_document.deny_insecure_transport[0]", + "data.aws_iam_policy_document.deny_insecure_transport", + "var.attach_deny_unencrypted_object_uploads", + "data.aws_iam_policy_document.deny_unencrypted_object_uploads[0].json", + "data.aws_iam_policy_document.deny_unencrypted_object_uploads[0]", + "data.aws_iam_policy_document.deny_unencrypted_object_uploads", + "var.attach_deny_incorrect_kms_key_sse", + "data.aws_iam_policy_document.deny_incorrect_kms_key_sse[0].json", + "data.aws_iam_policy_document.deny_incorrect_kms_key_sse[0]", + "data.aws_iam_policy_document.deny_incorrect_kms_key_sse", + "var.attach_deny_incorrect_encryption_headers", + "data.aws_iam_policy_document.deny_incorrect_encryption_headers[0].json", + "data.aws_iam_policy_document.deny_incorrect_encryption_headers[0]", + "data.aws_iam_policy_document.deny_incorrect_encryption_headers", + "var.attach_inventory_destination_policy", + "var.attach_analytics_destination_policy", + "data.aws_iam_policy_document.inventory_and_analytics_destination_policy[0].json", + "data.aws_iam_policy_document.inventory_and_analytics_destination_policy[0]", + "data.aws_iam_policy_document.inventory_and_analytics_destination_policy", + "var.attach_policy", + "var.policy" + ] + } + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "local.attach_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.deny_incorrect_encryption_headers", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "deny_incorrect_encryption_headers", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringNotEquals" + }, + "values": { + "references": [ + "var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm", + "var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default", + "var.server_side_encryption_configuration.rule", + "var.server_side_encryption_configuration" + ] + }, + "variable": { + "constant_value": "s3:x-amz-server-side-encryption" + } + } + ], + "effect": { + "constant_value": "Deny" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "*" + ] + }, + "type": { + "constant_value": "*" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "denyIncorrectEncryptionHeaders" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_deny_incorrect_encryption_headers" + ] + } + }, + { + "address": "data.aws_iam_policy_document.deny_incorrect_kms_key_sse", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "deny_incorrect_kms_key_sse", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringNotEquals" + }, + "values": { + "references": [ + "var.allowed_kms_key_arn" + ] + }, + "variable": { + "constant_value": "s3:x-amz-server-side-encryption-aws-kms-key-id" + } + } + ], + "effect": { + "constant_value": "Deny" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "*" + ] + }, + "type": { + "constant_value": "*" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "denyIncorrectKmsKeySse" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_deny_incorrect_kms_key_sse" + ] + } + }, + { + "address": "data.aws_iam_policy_document.deny_insecure_transport", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "deny_insecure_transport", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:*" + ] + }, + "condition": [ + { + "test": { + "constant_value": "Bool" + }, + "values": { + "constant_value": [ + "false" + ] + }, + "variable": { + "constant_value": "aws:SecureTransport" + } + } + ], + "effect": { + "constant_value": "Deny" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "*" + ] + }, + "type": { + "constant_value": "*" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this", + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "denyInsecureTransport" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_deny_insecure_transport_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.deny_unencrypted_object_uploads", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "deny_unencrypted_object_uploads", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "Null" + }, + "values": { + "constant_value": [ + true + ] + }, + "variable": { + "constant_value": "s3:x-amz-server-side-encryption" + } + } + ], + "effect": { + "constant_value": "Deny" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "*" + ] + }, + "type": { + "constant_value": "*" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "denyUnencryptedObjectUploads" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_deny_unencrypted_object_uploads" + ] + } + }, + { + "address": "data.aws_iam_policy_document.elb_log_delivery", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "elb_log_delivery", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "logdelivery.elasticloadbalancing.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_elb_log_delivery_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.inventory_and_analytics_destination_policy", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "inventory_and_analytics_destination_policy", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "ArnLike" + }, + "values": { + "references": [ + "var.inventory_self_source_destination", + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this", + "var.inventory_source_bucket_arn", + "var.analytics_self_source_destination", + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this", + "var.analytics_source_bucket_arn" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + }, + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "var.inventory_self_source_destination", + "data.aws_caller_identity.current.id", + "data.aws_caller_identity.current", + "var.inventory_source_account_id", + "var.analytics_self_source_destination", + "data.aws_caller_identity.current.id", + "data.aws_caller_identity.current", + "var.analytics_source_account_id" + ] + }, + "variable": { + "constant_value": "aws:SourceAccount" + } + }, + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "constant_value": [ + "bucket-owner-full-control" + ] + }, + "variable": { + "constant_value": "s3:x-amz-acl" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "destinationInventoryAndAnalyticsPolicy" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_inventory_destination_policy", + "var.attach_analytics_destination_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.lb_log_delivery", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "lb_log_delivery", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "constant_value": [ + "bucket-owner-full-control" + ] + }, + "variable": { + "constant_value": "s3:x-amz-acl" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "delivery.logs.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "AWSLogDeliveryWrite" + } + }, + { + "actions": { + "constant_value": [ + "s3:GetBucketAcl", + "s3:ListBucket" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "delivery.logs.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "AWSLogDeliveryAclCheck" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_lb_log_delivery_policy" + ] + } + }, + { + "address": "data.aws_iam_policy_document.require_latest_tls", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "require_latest_tls", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:*" + ] + }, + "condition": [ + { + "test": { + "constant_value": "NumericLessThan" + }, + "values": { + "constant_value": [ + "1.2" + ] + }, + "variable": { + "constant_value": "s3:TlsVersion" + } + } + ], + "effect": { + "constant_value": "Deny" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "*" + ] + }, + "type": { + "constant_value": "*" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this", + "aws_s3_bucket.this[0].arn", + "aws_s3_bucket.this[0]", + "aws_s3_bucket.this" + ] + }, + "sid": { + "constant_value": "denyOutdatedTLS" + } + } + ] + }, + "schema_version": 0, + "count_expression": { + "references": [ + "local.create_bucket", + "var.attach_require_latest_tls_policy" + ] + } + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + } + ], + "variables": { + "acceleration_status": { + "default": null, + "description": "(Optional) Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended." + }, + "access_log_delivery_policy_source_accounts": { + "default": [], + "description": "(Optional) List of AWS Account IDs should be allowed to deliver access logs to this bucket." + }, + "access_log_delivery_policy_source_buckets": { + "default": [], + "description": "(Optional) List of S3 bucket ARNs wich should be allowed to deliver access logs to this bucket." + }, + "acl": { + "default": null, + "description": "(Optional) The canned ACL to apply. Conflicts with `grant`" + }, + "allowed_kms_key_arn": { + "default": null, + "description": "The ARN of KMS key which should be allowed in PutObject" + }, + "analytics_configuration": { + "default": {}, + "description": "Map containing bucket analytics configuration." + }, + "analytics_self_source_destination": { + "default": false, + "description": "Whether or not the analytics source bucket is also the destination bucket." + }, + "analytics_source_account_id": { + "default": null, + "description": "The analytics source account id." + }, + "analytics_source_bucket_arn": { + "default": null, + "description": "The analytics source bucket ARN." + }, + "attach_access_log_delivery_policy": { + "default": false, + "description": "Controls if S3 bucket should have S3 access log delivery policy attached" + }, + "attach_analytics_destination_policy": { + "default": false, + "description": "Controls if S3 bucket should have bucket analytics destination policy attached." + }, + "attach_deny_incorrect_encryption_headers": { + "default": false, + "description": "Controls if S3 bucket should deny incorrect encryption headers policy attached." + }, + "attach_deny_incorrect_kms_key_sse": { + "default": false, + "description": "Controls if S3 bucket policy should deny usage of incorrect KMS key SSE." + }, + "attach_deny_insecure_transport_policy": { + "default": false, + "description": "Controls if S3 bucket should have deny non-SSL transport policy attached" + }, + "attach_deny_unencrypted_object_uploads": { + "default": false, + "description": "Controls if S3 bucket should deny unencrypted object uploads policy attached." + }, + "attach_elb_log_delivery_policy": { + "default": false, + "description": "Controls if S3 bucket should have ELB log delivery policy attached" + }, + "attach_inventory_destination_policy": { + "default": false, + "description": "Controls if S3 bucket should have bucket inventory destination policy attached." + }, + "attach_lb_log_delivery_policy": { + "default": false, + "description": "Controls if S3 bucket should have ALB/NLB log delivery policy attached" + }, + "attach_policy": { + "default": false, + "description": "Controls if S3 bucket should have bucket policy attached (set to `true` to use value of `policy` as bucket policy)" + }, + "attach_public_policy": { + "default": true, + "description": "Controls if a user defined public bucket policy will be attached (set to `false` to allow upstream to apply defaults to the bucket)" + }, + "attach_require_latest_tls_policy": { + "default": false, + "description": "Controls if S3 bucket should require the latest version of TLS" + }, + "block_public_acls": { + "default": true, + "description": "Whether Amazon S3 should block public ACLs for this bucket." + }, + "block_public_policy": { + "default": true, + "description": "Whether Amazon S3 should block public bucket policies for this bucket." + }, + "bucket": { + "default": null, + "description": "(Optional, Forces new resource) The name of the bucket. If omitted, Terraform will assign a random, unique name." + }, + "bucket_prefix": { + "default": null, + "description": "(Optional, Forces new resource) Creates a unique bucket name beginning with the specified prefix. Conflicts with bucket." + }, + "control_object_ownership": { + "default": false, + "description": "Whether to manage S3 Bucket Ownership Controls on this bucket." + }, + "cors_rule": { + "default": [], + "description": "List of maps containing rules for Cross-Origin Resource Sharing." + }, + "create_bucket": { + "default": true, + "description": "Controls if S3 bucket should be created" + }, + "expected_bucket_owner": { + "default": null, + "description": "The account ID of the expected bucket owner" + }, + "force_destroy": { + "default": false, + "description": "(Optional, Default:false ) A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable." + }, + "grant": { + "default": [], + "description": "An ACL policy grant. Conflicts with `acl`" + }, + "ignore_public_acls": { + "default": true, + "description": "Whether Amazon S3 should ignore public ACLs for this bucket." + }, + "intelligent_tiering": { + "default": {}, + "description": "Map containing intelligent tiering configuration." + }, + "inventory_configuration": { + "default": {}, + "description": "Map containing S3 inventory configuration." + }, + "inventory_self_source_destination": { + "default": false, + "description": "Whether or not the inventory source bucket is also the destination bucket." + }, + "inventory_source_account_id": { + "default": null, + "description": "The inventory source account id." + }, + "inventory_source_bucket_arn": { + "default": null, + "description": "The inventory source bucket ARN." + }, + "lifecycle_rule": { + "default": [], + "description": "List of maps containing configuration of object lifecycle management." + }, + "logging": { + "default": {}, + "description": "Map containing access bucket logging configuration." + }, + "metric_configuration": { + "default": [], + "description": "Map containing bucket metric configuration." + }, + "object_lock_configuration": { + "default": {}, + "description": "Map containing S3 object locking configuration." + }, + "object_lock_enabled": { + "default": false, + "description": "Whether S3 bucket should have an Object Lock configuration enabled." + }, + "object_ownership": { + "default": "BucketOwnerEnforced", + "description": "Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL." + }, + "owner": { + "default": {}, + "description": "Bucket owner's display name and ID. Conflicts with `acl`" + }, + "policy": { + "default": null, + "description": "(Optional) A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy. For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide." + }, + "putin_khuylo": { + "default": true, + "description": "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!" + }, + "replication_configuration": { + "default": {}, + "description": "Map containing cross-region replication configuration." + }, + "request_payer": { + "default": null, + "description": "(Optional) Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. By default, the owner of the S3 bucket would incur the costs of any data transfer. See Requester Pays Buckets developer guide for more information." + }, + "restrict_public_buckets": { + "default": true, + "description": "Whether Amazon S3 should restrict public bucket policies for this bucket." + }, + "server_side_encryption_configuration": { + "default": {}, + "description": "Map containing server-side encryption configuration." + }, + "tags": { + "default": {}, + "description": "(Optional) A mapping of tags to assign to the bucket." + }, + "versioning": { + "default": {}, + "description": "Map containing versioning configuration." + }, + "website": { + "default": {}, + "description": "Map containing static web-site hosting or redirect configuration." + } + } + }, + "version_constraint": "~> 3.0" + } + }, + "variables": { + "aws_region": { + "default": "us-east-1", + "description": "AWS region" + }, + "bucket_name": { + "default": "my-react-static-website", + "description": "S3 bucket name for static website" + } + } + } + }, + "relevant_attributes": [ + { + "resource": "module.cloudfront.data.aws_cloudfront_cache_policy.this", + "attribute": [] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "caller_reference" + ] + }, + { + "resource": "module.cloudfront.data.aws_cloudfront_origin_request_policy.this", + "attribute": [] + }, + { + "resource": "module.cloudfront.data.aws_cloudfront_response_headers_policy.this", + "attribute": [] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "etag" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "status" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket_policy.this[0]", + "attribute": [ + "policy" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "in_progress_validation_batches" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_origin_access_identity.this", + "attribute": [] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "domain_name" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "tags_all" + ] + }, + { + "resource": "module.s3_bucket.data.aws_iam_policy_document.combined[0]", + "attribute": [ + "json" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket_policy.this[0]", + "attribute": [ + "id" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "hosted_zone_id" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket_lifecycle_configuration.this[0]", + "attribute": [ + "rule" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "trusted_signers" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "bucket_domain_name" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "id" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "id" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "hosted_zone_id" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "last_modified_time" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_origin_access_control.this", + "attribute": [] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "bucket_regional_domain_name" + ] + }, + { + "resource": "module.s3_bucket.data.aws_canonical_user_id.this[0]", + "attribute": [ + "id" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "arn" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "attribute": [ + "arn" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]", + "attribute": [ + "website_domain" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket.this[0]", + "attribute": [ + "region" + ] + }, + { + "resource": "module.cloudfront.aws_cloudfront_monitoring_subscription.this[0]", + "attribute": [ + "id" + ] + }, + { + "resource": "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]", + "attribute": [ + "website_endpoint" + ] + } + ], + "timestamp": "2025-12-25T09:13:39Z", + "applyable": true, + "complete": true, + "errored": false + }, + "tf_resources_created": [ + { + "address": "module.cloudfront.aws_cloudfront_distribution.this[0]", + "module_address": "module.cloudfront", + "mode": "managed", + "type": "aws_cloudfront_distribution", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "aliases": null, + "comment": "CloudFront distribution for my-react-static-website", + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "default_root_object": "index.html", + "enabled": true, + "http_version": "http2", + "is_ipv6_enabled": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "price_class": "PriceClass_100", + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "retain_on_delete": false, + "staging": false, + "tags": null, + "viewer_certificate": [ + {} + ], + "wait_for_deployment": true, + "web_acl_id": null, + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "status": true, + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "module": "cloudfront" + }, + "after_unknown": { + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "default_ttl": true, + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": true + } + ], + "headers": true, + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": true, + "lambda_function_association": [], + "max_ttl": true, + "trusted_key_groups": true, + "trusted_signers": true + } + ], + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "domain_name": true, + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "restrictions": [ + { + "geo_restriction": [ + { + "locations": true + } + ] + } + ], + "status": true, + "tags_all": true, + "trusted_key_groups": true, + "trusted_signers": true, + "viewer_certificate": [ + {} + ] + }, + "before_sensitive": false, + "after_sensitive": { + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "viewer_certificate": [ + {} + ] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "my-react-static-website", + "force_destroy": false, + "object_lock_enabled": false, + "tags": null, + "timeouts": null, + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": [], + "grant": [], + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "policy": true, + "region": true, + "replication_configuration": [], + "request_payer": true, + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [], + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_acl.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "private", + "expected_bucket_owner": null, + "access_control_policy": [], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false, + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_versioning.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + {} + ], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + }, + { + "address": "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]", + "module_address": "module.s3_bucket", + "mode": "managed", + "type": "aws_s3_bucket_website_configuration", + "name": "this", + "index": 0, + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "error_document": [ + {} + ], + "expected_bucket_owner": null, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "bucket": true, + "id": true, + "routing_rule": [], + "routing_rules": true, + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "after_unknown": { + "bucket": true, + "error_document": [ + {} + ], + "id": true, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "routing_rule": true, + "routing_rules": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "error_document": [ + {} + ], + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "routing_rule": [] + } + } + } + ], + "tfgraph": { + "name": "G", + "directed": true, + "strict": false, + "label": "", + "rankdir": "RL", + "_subgraph_cnt": 2, + "objects": [ + { + "name": "cluster_module.cloudfront", + "fontname": "sans-serif", + "label": "module.cloudfront", + "rankdir": "RL", + "_gvid": 0, + "nodes": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ], + "edges": [ + 0, + 1, + 2, + 3, + 4, + 6 + ] + }, + { + "name": "cluster_module.s3_bucket", + "fontname": "sans-serif", + "label": "module.s3_bucket", + "rankdir": "RL", + "_gvid": 1, + "nodes": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41 + ], + "edges": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48 + ] + }, + { + "_gvid": 2, + "name": "module.cloudfront.data.aws_cloudfront_cache_policy.this", + "fontname": "sans-serif", + "label": "data.aws_cloudfront_cache_policy.this", + "shape": "rect" + }, + { + "_gvid": 3, + "name": "module.cloudfront.data.aws_cloudfront_origin_request_policy.this", + "fontname": "sans-serif", + "label": "data.aws_cloudfront_origin_request_policy.this", + "shape": "rect" + }, + { + "_gvid": 4, + "name": "module.cloudfront.data.aws_cloudfront_response_headers_policy.this", + "fontname": "sans-serif", + "label": "data.aws_cloudfront_response_headers_policy.this", + "shape": "rect" + }, + { + "_gvid": 5, + "name": "module.cloudfront.aws_cloudfront_distribution.this", + "fontname": "sans-serif", + "label": "aws_cloudfront_distribution.this", + "shape": "rect" + }, + { + "_gvid": 6, + "name": "module.cloudfront.aws_cloudfront_monitoring_subscription.this", + "fontname": "sans-serif", + "label": "aws_cloudfront_monitoring_subscription.this", + "shape": "rect" + }, + { + "_gvid": 7, + "name": "module.cloudfront.aws_cloudfront_origin_access_control.this", + "fontname": "sans-serif", + "label": "aws_cloudfront_origin_access_control.this", + "shape": "rect" + }, + { + "_gvid": 8, + "name": "module.cloudfront.aws_cloudfront_origin_access_identity.this", + "fontname": "sans-serif", + "label": "aws_cloudfront_origin_access_identity.this", + "shape": "rect" + }, + { + "_gvid": 9, + "name": "module.s3_bucket.data.aws_caller_identity.current", + "fontname": "sans-serif", + "label": "data.aws_caller_identity.current", + "shape": "rect" + }, + { + "_gvid": 10, + "name": "module.s3_bucket.data.aws_canonical_user_id.this", + "fontname": "sans-serif", + "label": "data.aws_canonical_user_id.this", + "shape": "rect" + }, + { + "_gvid": 11, + "name": "module.s3_bucket.data.aws_iam_policy_document.access_log_delivery", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.access_log_delivery", + "shape": "rect" + }, + { + "_gvid": 12, + "name": "module.s3_bucket.data.aws_iam_policy_document.combined", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.combined", + "shape": "rect" + }, + { + "_gvid": 13, + "name": "module.s3_bucket.data.aws_iam_policy_document.deny_incorrect_encryption_headers", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.deny_incorrect_encryption_headers", + "shape": "rect" + }, + { + "_gvid": 14, + "name": "module.s3_bucket.data.aws_iam_policy_document.deny_incorrect_kms_key_sse", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.deny_incorrect_kms_key_sse", + "shape": "rect" + }, + { + "_gvid": 15, + "name": "module.s3_bucket.data.aws_iam_policy_document.deny_insecure_transport", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.deny_insecure_transport", + "shape": "rect" + }, + { + "_gvid": 16, + "name": "module.s3_bucket.data.aws_iam_policy_document.deny_unencrypted_object_uploads", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.deny_unencrypted_object_uploads", + "shape": "rect" + }, + { + "_gvid": 17, + "name": "module.s3_bucket.data.aws_iam_policy_document.elb_log_delivery", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.elb_log_delivery", + "shape": "rect" + }, + { + "_gvid": 18, + "name": "module.s3_bucket.data.aws_iam_policy_document.inventory_and_analytics_destination_policy", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.inventory_and_analytics_destination_policy", + "shape": "rect" + }, + { + "_gvid": 19, + "name": "module.s3_bucket.data.aws_iam_policy_document.lb_log_delivery", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.lb_log_delivery", + "shape": "rect" + }, + { + "_gvid": 20, + "name": "module.s3_bucket.data.aws_iam_policy_document.require_latest_tls", + "fontname": "sans-serif", + "label": "data.aws_iam_policy_document.require_latest_tls", + "shape": "rect" + }, + { + "_gvid": 21, + "name": "module.s3_bucket.data.aws_partition.current", + "fontname": "sans-serif", + "label": "data.aws_partition.current", + "shape": "rect" + }, + { + "_gvid": 22, + "name": "module.s3_bucket.data.aws_region.current", + "fontname": "sans-serif", + "label": "data.aws_region.current", + "shape": "rect" + }, + { + "_gvid": 23, + "name": "module.s3_bucket.aws_s3_bucket.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket.this", + "shape": "rect" + }, + { + "_gvid": 24, + "name": "module.s3_bucket.aws_s3_bucket_accelerate_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_accelerate_configuration.this", + "shape": "rect" + }, + { + "_gvid": 25, + "name": "module.s3_bucket.aws_s3_bucket_acl.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_acl.this", + "shape": "rect" + }, + { + "_gvid": 26, + "name": "module.s3_bucket.aws_s3_bucket_analytics_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_analytics_configuration.this", + "shape": "rect" + }, + { + "_gvid": 27, + "name": "module.s3_bucket.aws_s3_bucket_cors_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_cors_configuration.this", + "shape": "rect" + }, + { + "_gvid": 28, + "name": "module.s3_bucket.aws_s3_bucket_intelligent_tiering_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_intelligent_tiering_configuration.this", + "shape": "rect" + }, + { + "_gvid": 29, + "name": "module.s3_bucket.aws_s3_bucket_inventory.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_inventory.this", + "shape": "rect" + }, + { + "_gvid": 30, + "name": "module.s3_bucket.aws_s3_bucket_lifecycle_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_lifecycle_configuration.this", + "shape": "rect" + }, + { + "_gvid": 31, + "name": "module.s3_bucket.aws_s3_bucket_logging.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_logging.this", + "shape": "rect" + }, + { + "_gvid": 32, + "name": "module.s3_bucket.aws_s3_bucket_metric.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_metric.this", + "shape": "rect" + }, + { + "_gvid": 33, + "name": "module.s3_bucket.aws_s3_bucket_object_lock_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_object_lock_configuration.this", + "shape": "rect" + }, + { + "_gvid": 34, + "name": "module.s3_bucket.aws_s3_bucket_ownership_controls.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_ownership_controls.this", + "shape": "rect" + }, + { + "_gvid": 35, + "name": "module.s3_bucket.aws_s3_bucket_policy.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_policy.this", + "shape": "rect" + }, + { + "_gvid": 36, + "name": "module.s3_bucket.aws_s3_bucket_public_access_block.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_public_access_block.this", + "shape": "rect" + }, + { + "_gvid": 37, + "name": "module.s3_bucket.aws_s3_bucket_replication_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_replication_configuration.this", + "shape": "rect" + }, + { + "_gvid": 38, + "name": "module.s3_bucket.aws_s3_bucket_request_payment_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_request_payment_configuration.this", + "shape": "rect" + }, + { + "_gvid": 39, + "name": "module.s3_bucket.aws_s3_bucket_server_side_encryption_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_server_side_encryption_configuration.this", + "shape": "rect" + }, + { + "_gvid": 40, + "name": "module.s3_bucket.aws_s3_bucket_versioning.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_versioning.this", + "shape": "rect" + }, + { + "_gvid": 41, + "name": "module.s3_bucket.aws_s3_bucket_website_configuration.this", + "fontname": "sans-serif", + "label": "aws_s3_bucket_website_configuration.this", + "shape": "rect" + } + ], + "edges": [ + { + "_gvid": 0, + "tail": 5, + "head": 2 + }, + { + "_gvid": 1, + "tail": 5, + "head": 3 + }, + { + "_gvid": 2, + "tail": 5, + "head": 4 + }, + { + "_gvid": 3, + "tail": 5, + "head": 7 + }, + { + "_gvid": 4, + "tail": 5, + "head": 8 + }, + { + "_gvid": 5, + "tail": 5, + "head": 23 + }, + { + "_gvid": 6, + "tail": 6, + "head": 5 + }, + { + "_gvid": 7, + "tail": 11, + "head": 23 + }, + { + "_gvid": 8, + "tail": 12, + "head": 11 + }, + { + "_gvid": 9, + "tail": 12, + "head": 13 + }, + { + "_gvid": 10, + "tail": 12, + "head": 14 + }, + { + "_gvid": 11, + "tail": 12, + "head": 15 + }, + { + "_gvid": 12, + "tail": 12, + "head": 16 + }, + { + "_gvid": 13, + "tail": 12, + "head": 17 + }, + { + "_gvid": 14, + "tail": 12, + "head": 18 + }, + { + "_gvid": 15, + "tail": 12, + "head": 19 + }, + { + "_gvid": 16, + "tail": 12, + "head": 20 + }, + { + "_gvid": 17, + "tail": 13, + "head": 23 + }, + { + "_gvid": 18, + "tail": 14, + "head": 23 + }, + { + "_gvid": 19, + "tail": 15, + "head": 23 + }, + { + "_gvid": 20, + "tail": 16, + "head": 23 + }, + { + "_gvid": 21, + "tail": 17, + "head": 21 + }, + { + "_gvid": 22, + "tail": 17, + "head": 22 + }, + { + "_gvid": 23, + "tail": 17, + "head": 23 + }, + { + "_gvid": 24, + "tail": 18, + "head": 9 + }, + { + "_gvid": 25, + "tail": 18, + "head": 23 + }, + { + "_gvid": 26, + "tail": 19, + "head": 23 + }, + { + "_gvid": 27, + "tail": 20, + "head": 23 + }, + { + "_gvid": 28, + "tail": 24, + "head": 23 + }, + { + "_gvid": 29, + "tail": 25, + "head": 10 + }, + { + "_gvid": 30, + "tail": 25, + "head": 34 + }, + { + "_gvid": 31, + "tail": 26, + "head": 9 + }, + { + "_gvid": 32, + "tail": 26, + "head": 23 + }, + { + "_gvid": 33, + "tail": 27, + "head": 23 + }, + { + "_gvid": 34, + "tail": 28, + "head": 23 + }, + { + "_gvid": 35, + "tail": 29, + "head": 23 + }, + { + "_gvid": 36, + "tail": 30, + "head": 40 + }, + { + "_gvid": 37, + "tail": 31, + "head": 23 + }, + { + "_gvid": 38, + "tail": 32, + "head": 23 + }, + { + "_gvid": 39, + "tail": 33, + "head": 23 + }, + { + "_gvid": 40, + "tail": 34, + "head": 35 + }, + { + "_gvid": 41, + "tail": 35, + "head": 12 + }, + { + "_gvid": 42, + "tail": 35, + "head": 36 + }, + { + "_gvid": 43, + "tail": 36, + "head": 23 + }, + { + "_gvid": 44, + "tail": 37, + "head": 40 + }, + { + "_gvid": 45, + "tail": 38, + "head": 23 + }, + { + "_gvid": 46, + "tail": 39, + "head": 23 + }, + { + "_gvid": 47, + "tail": 40, + "head": 23 + }, + { + "_gvid": 48, + "tail": 41, + "head": 23 + } + ] + }, + "graphdict": { + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": [] + }, + "meta_data": { + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": { + "aliases": null, + "comment": "CloudFront distribution for my-react-static-website", + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "default_root_object": "index.html", + "enabled": true, + "http_version": "http2", + "is_ipv6_enabled": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "price_class": "PriceClass_100", + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "retain_on_delete": false, + "staging": false, + "tags": null, + "viewer_certificate": [ + {} + ], + "wait_for_deployment": true, + "web_acl_id": null, + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "status": true, + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "module": "cloudfront" + }, + "module.s3_bucket.aws_s3_bucket.this[0]~1": { + "bucket": "my-react-static-website", + "force_destroy": false, + "object_lock_enabled": false, + "tags": null, + "timeouts": null, + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": [], + "grant": [], + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "policy": true, + "region": true, + "replication_configuration": [], + "request_payer": true, + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [], + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": { + "acl": "private", + "expected_bucket_owner": null, + "access_control_policy": [], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false, + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + {} + ], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": { + "error_document": [ + {} + ], + "expected_bucket_owner": null, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "bucket": true, + "id": true, + "routing_rule": [], + "routing_rules": true, + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + } + }, + "all_output": { + "/Users/patrick/git/terravision/tests/fixtures/aws_terraform/static-website/outputs.tf": [ + { + "cloudfront_distribution_domain_name": { + "description": "CloudFront distribution domain name", + "value": "${module.cloudfront.cloudfront_distribution_domain_name}" + } + }, + { + "s3_bucket_name": { + "description": "S3 bucket name", + "value": "${module.s3_bucket.s3_bucket_id}" + } + }, + { + "website_url": { + "description": "Website URL", + "value": "https://${module.cloudfront.cloudfront_distribution_domain_name}" + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/outputs.tf": [ + { + "s3_bucket_id": { + "description": "The name of the bucket.", + "value": "${try(aws_s3_bucket.this[0].id, aws_s3_directory_bucket.this[0].bucket, \"\")}" + } + }, + { + "s3_bucket_arn": { + "description": "The ARN of the bucket. Will be of format arn:aws:s3:::bucketname.", + "value": "${try(aws_s3_bucket.this[0].arn, \"\")}" + } + }, + { + "s3_bucket_bucket_domain_name": { + "description": "The bucket domain name. Will be of format bucketname.s3.amazonaws.com.", + "value": "${try(aws_s3_bucket.this[0].bucket_domain_name, \"\")}" + } + }, + { + "s3_bucket_bucket_regional_domain_name": { + "description": "The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL.", + "value": "${try(aws_s3_bucket.this[0].bucket_regional_domain_name, \"\")}" + } + }, + { + "s3_bucket_hosted_zone_id": { + "description": "The Route 53 Hosted Zone ID for this bucket's region.", + "value": "${try(aws_s3_bucket.this[0].hosted_zone_id, \"\")}" + } + }, + { + "s3_bucket_lifecycle_configuration_rules": { + "description": "The lifecycle rules of the bucket, if the bucket is configured with lifecycle rules. If not, this will be an empty string.", + "value": "${try(aws_s3_bucket_lifecycle_configuration.this[0].rule, \"\")}" + } + }, + { + "s3_bucket_policy": { + "description": "The policy of the bucket, if the bucket is configured with a policy. If not, this will be an empty string.", + "value": "${try(aws_s3_bucket_policy.this[0].policy, \"\")}" + } + }, + { + "s3_bucket_region": { + "description": "The AWS region this bucket resides in.", + "value": "${try(aws_s3_bucket.this[0].bucket_region, \"\")}" + } + }, + { + "s3_bucket_website_endpoint": { + "description": "The website endpoint, if the bucket is configured with a website. If not, this will be an empty string.", + "value": "${try(aws_s3_bucket_website_configuration.this[0].website_endpoint, \"\")}" + } + }, + { + "s3_bucket_website_domain": { + "description": "The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records.", + "value": "${try(aws_s3_bucket_website_configuration.this[0].website_domain, \"\")}" + } + }, + { + "s3_directory_bucket_name": { + "description": "Name of the directory bucket.", + "value": "${try(aws_s3_directory_bucket.this[0].bucket, None)}" + } + }, + { + "s3_directory_bucket_arn": { + "description": "ARN of the directory bucket.", + "value": "${try(aws_s3_directory_bucket.this[0].arn, None)}" + } + }, + { + "aws_s3_bucket_versioning_status": { + "description": "The versioning status of the bucket. Will be 'Enabled', 'Suspended', or 'Disabled'.", + "value": "${try(aws_s3_bucket_versioning.this[0].versioning_configuration[0].status, None)}" + } + }, + { + "s3_bucket_tags": { + "description": "Tags of the bucket.", + "value": "${try(aws_s3_bucket.this[0].tags, {})}" + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/outputs.tf": [ + { + "cloudfront_distribution_id": { + "description": "The identifier for the distribution.", + "value": "${try(aws_cloudfront_distribution.this[0].id, None)}" + } + }, + { + "cloudfront_distribution_arn": { + "description": "The ARN (Amazon Resource Name) for the distribution.", + "value": "${try(aws_cloudfront_distribution.this[0].arn, None)}" + } + }, + { + "cloudfront_distribution_caller_reference": { + "description": "Internal value used by CloudFront to allow future updates to the distribution configuration.", + "value": "${try(aws_cloudfront_distribution.this[0].caller_reference, None)}" + } + }, + { + "cloudfront_distribution_status": { + "description": "The current status of the distribution. Deployed if the distribution's information is fully propagated throughout the Amazon CloudFront system.", + "value": "${try(aws_cloudfront_distribution.this[0].status, None)}" + } + }, + { + "cloudfront_distribution_trusted_signers": { + "description": "List of nested attributes for active trusted signers, if the distribution is set up to serve private content with signed URLs", + "value": "${try(aws_cloudfront_distribution.this[0].trusted_signers, None)}" + } + }, + { + "cloudfront_distribution_domain_name": { + "description": "The domain name corresponding to the distribution.", + "value": "${try(aws_cloudfront_distribution.this[0].domain_name, None)}" + } + }, + { + "cloudfront_distribution_last_modified_time": { + "description": "The date and time the distribution was last modified.", + "value": "${try(aws_cloudfront_distribution.this[0].last_modified_time, None)}" + } + }, + { + "cloudfront_distribution_in_progress_validation_batches": { + "description": "The number of invalidation batches currently in progress.", + "value": "${try(aws_cloudfront_distribution.this[0].in_progress_validation_batches, None)}" + } + }, + { + "cloudfront_distribution_etag": { + "description": "The current version of the distribution's information.", + "value": "${try(aws_cloudfront_distribution.this[0].etag, None)}" + } + }, + { + "cloudfront_distribution_hosted_zone_id": { + "description": "The CloudFront Route 53 zone ID that can be used to route an Alias Resource Record Set to.", + "value": "${try(aws_cloudfront_distribution.this[0].hosted_zone_id, None)}" + } + }, + { + "cloudfront_origin_access_controls": { + "description": "The origin access controls created", + "value": "${aws_cloudfront_origin_access_control.this}" + } + }, + { + "cloudfront_vpc_origins": { + "description": "The IDS of the VPC origin created", + "value": "${aws_cloudfront_vpc_origin.this}" + } + }, + { + "cloudfront_response_headers_policies": { + "description": "The response headers policies created", + "value": "${aws_cloudfront_response_headers_policy.this}" + } + }, + { + "cloudfront_functions": { + "description": "The CloudFront Functions created", + "value": "${aws_cloudfront_function.this}" + } + }, + { + "cloudfront_monitoring_subscription_id": { + "description": " The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`.", + "value": "${try(aws_cloudfront_monitoring_subscription.this[0].id, None)}" + } + } + ] + }, + "node_list": [ + "module.cloudfront.aws_cloudfront_distribution.this[0]~1", + "module.s3_bucket.aws_s3_bucket.this[0]~1", + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1", + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1", + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1", + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1" + ], + "hidden": {}, + "annotations": {}, + "original_graphdict": { + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": [], + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": [] + }, + "original_metadata": { + "module.cloudfront.aws_cloudfront_distribution.this[0]~1": { + "aliases": null, + "comment": "CloudFront distribution for my-react-static-website", + "custom_error_response": [], + "default_cache_behavior": [ + { + "allowed_methods": [ + false, + false + ], + "cached_methods": [ + false, + false + ], + "forwarded_values": [ + { + "cookies": [ + { + "whitelisted_names": [] + } + ], + "headers": [], + "query_string_cache_keys": [] + } + ], + "function_association": [], + "grpc_config": [], + "lambda_function_association": [], + "trusted_key_groups": [], + "trusted_signers": [] + } + ], + "default_root_object": "index.html", + "enabled": true, + "http_version": "http2", + "is_ipv6_enabled": true, + "logging_config": [], + "ordered_cache_behavior": [], + "origin": [ + { + "custom_header": [], + "custom_origin_config": [], + "origin_shield": [], + "s3_origin_config": [], + "vpc_origin_config": [] + } + ], + "origin_group": [], + "price_class": "PriceClass_100", + "restrictions": [ + { + "geo_restriction": [ + { + "locations": [] + } + ] + } + ], + "retain_on_delete": false, + "staging": false, + "tags": null, + "viewer_certificate": [ + {} + ], + "wait_for_deployment": true, + "web_acl_id": null, + "arn": true, + "caller_reference": true, + "continuous_deployment_policy_id": true, + "domain_name": true, + "etag": true, + "hosted_zone_id": true, + "id": true, + "in_progress_validation_batches": true, + "last_modified_time": true, + "status": true, + "tags_all": {}, + "trusted_key_groups": [], + "trusted_signers": [], + "module": "cloudfront" + }, + "module.s3_bucket.aws_s3_bucket.this[0]~1": { + "bucket": "my-react-static-website", + "force_destroy": false, + "object_lock_enabled": false, + "tags": null, + "timeouts": null, + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": [], + "grant": [], + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "policy": true, + "region": true, + "replication_configuration": [], + "request_payer": true, + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [], + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_acl.this[0]~1": { + "acl": "private", + "expected_bucket_owner": null, + "access_control_policy": [], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_public_access_block.this[0]~1": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false, + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_versioning.this[0]~1": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + {} + ], + "bucket": true, + "id": true, + "module": "s3_bucket" + }, + "module.s3_bucket.aws_s3_bucket_website_configuration.this[0]~1": { + "error_document": [ + {} + ], + "expected_bucket_owner": null, + "index_document": [ + {} + ], + "redirect_all_requests_to": [], + "bucket": true, + "id": true, + "routing_rule": [], + "routing_rules": true, + "website_domain": true, + "website_endpoint": true, + "module": "s3_bucket" + } + }, + "module_source_dict": { + "s3_bucket": "terraform-aws-modules/s3-bucket/aws", + "cloudfront": "terraform-aws-modules/cloudfront/aws" + }, + "all_module": { + "/Users/patrick/git/terravision/tests/fixtures/aws_terraform/static-website/main.tf": [ + { + "s3_bucket": { + "source": "terraform-aws-modules/s3-bucket/aws", + "version": "~> 3.0", + "bucket": "${var.bucket_name}", + "acl": "private", + "versioning": { + "enabled": true + }, + "website": { + "index_document": "index.html", + "error_document": "error.html" + }, + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + } + }, + { + "cloudfront": { + "source": "terraform-aws-modules/cloudfront/aws", + "version": "~> 3.0", + "comment": "CloudFront distribution for ${var.bucket_name}", + "enabled": true, + "is_ipv6_enabled": true, + "price_class": "PriceClass_100", + "default_root_object": "index.html", + "origin": { + "s3_bucket": { + "domain_name": "${module.s3_bucket.s3_bucket_bucket_regional_domain_name}", + "origin_id": "S3-${var.bucket_name}" + } + }, + "default_cache_behavior": { + "target_origin_id": "S3-${var.bucket_name}", + "viewer_protocol_policy": "redirect-to-https", + "allowed_methods": [ + "GET", + "HEAD" + ], + "cached_methods": [ + "GET", + "HEAD" + ], + "compress": true, + "forwarded_values": { + "query_string": false, + "cookies": { + "forward": "none" + } + } + }, + "viewer_certificate": { + "cloudfront_default_certificate": true + } + } + } + ] + }, + "all_variable": { + "/Users/patrick/git/terravision/tests/fixtures/aws_terraform/static-website/variables.tf": [ + { + "aws_region": { + "description": "AWS region", + "type": "${string}", + "default": "us-east-1" + } + }, + { + "bucket_name": { + "description": "S3 bucket name for static website", + "type": "${string}", + "default": "my-react-static-website" + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/variables.tf": [ + { + "create_bucket": { + "description": "Controls if S3 bucket should be created", + "type": "${bool}", + "default": true + } + }, + { + "attach_elb_log_delivery_policy": { + "description": "Controls if S3 bucket should have ELB log delivery policy attached", + "type": "${bool}", + "default": false + } + }, + { + "attach_lb_log_delivery_policy": { + "description": "Controls if S3 bucket should have ALB/NLB log delivery policy attached", + "type": "${bool}", + "default": false + } + }, + { + "attach_access_log_delivery_policy": { + "description": "Controls if S3 bucket should have S3 access log delivery policy attached", + "type": "${bool}", + "default": false + } + }, + { + "attach_cloudtrail_log_delivery_policy": { + "description": "Controls if S3 bucket should have CloudTrail log delivery policy attached", + "type": "${bool}", + "default": false + } + }, + { + "attach_deny_insecure_transport_policy": { + "description": "Controls if S3 bucket should have deny non-SSL transport policy attached", + "type": "${bool}", + "default": false + } + }, + { + "attach_require_latest_tls_policy": { + "description": "Controls if S3 bucket should require the latest version of TLS", + "type": "${bool}", + "default": false + } + }, + { + "attach_policy": { + "description": "Controls if S3 bucket should have bucket policy attached (set to `true` to use value of `policy` as bucket policy)", + "type": "${bool}", + "default": false + } + }, + { + "attach_public_policy": { + "description": "Controls if a user defined public bucket policy will be attached (set to `false` to allow upstream to apply defaults to the bucket)", + "type": "${bool}", + "default": true + } + }, + { + "attach_inventory_destination_policy": { + "description": "Controls if S3 bucket should have bucket inventory destination policy attached.", + "type": "${bool}", + "default": false + } + }, + { + "attach_analytics_destination_policy": { + "description": "Controls if S3 bucket should have bucket analytics destination policy attached.", + "type": "${bool}", + "default": false + } + }, + { + "attach_deny_incorrect_encryption_headers": { + "description": "Controls if S3 bucket should deny incorrect encryption headers policy attached.", + "type": "${bool}", + "default": false + } + }, + { + "attach_deny_incorrect_kms_key_sse": { + "description": "Controls if S3 bucket policy should deny usage of incorrect KMS key SSE.", + "type": "${bool}", + "default": false + } + }, + { + "allowed_kms_key_arn": { + "description": "The ARN of KMS key which should be allowed in PutObject", + "type": "${string}", + "default": null + } + }, + { + "attach_deny_unencrypted_object_uploads": { + "description": "Controls if S3 bucket should deny unencrypted object uploads policy attached.", + "type": "${bool}", + "default": false + } + }, + { + "attach_deny_ssec_encrypted_object_uploads": { + "description": "Controls if S3 bucket should deny SSEC encrypted object uploads.", + "type": "${bool}", + "default": false + } + }, + { + "attach_waf_log_delivery_policy": { + "description": "Controls if S3 bucket should have WAF log delivery policy attached", + "type": "${bool}", + "default": false + } + }, + { + "region": { + "description": "Region where the resource(s) will be managed. Defaults to the region set in the provider configuration", + "type": "${string}", + "default": null + } + }, + { + "bucket": { + "description": "(Optional, Forces new resource) The name of the bucket. If omitted, Terraform will assign a random, unique name.", + "type": "${string}", + "default": null + } + }, + { + "bucket_prefix": { + "description": "(Optional, Forces new resource) Creates a unique bucket name beginning with the specified prefix. Conflicts with bucket.", + "type": "${string}", + "default": null + } + }, + { + "acl": { + "description": "(Optional) The canned ACL to apply. Conflicts with `grant`", + "type": "${string}", + "default": null + } + }, + { + "policy": { + "description": "(Optional) A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy. For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide.", + "type": "${string}", + "default": null + } + }, + { + "tags": { + "description": "(Optional) A mapping of tags to assign to the bucket.", + "type": "${map(string)}", + "default": {} + } + }, + { + "force_destroy": { + "description": "(Optional, Default:false ) A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable.", + "type": "${bool}", + "default": false + } + }, + { + "acceleration_status": { + "description": "(Optional) Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended.", + "type": "${string}", + "default": null + } + }, + { + "request_payer": { + "description": "(Optional) Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. By default, the owner of the S3 bucket would incur the costs of any data transfer. See Requester Pays Buckets developer guide for more information.", + "type": "${string}", + "default": null + } + }, + { + "website": { + "description": "Map containing static web-site hosting or redirect configuration.", + "type": "${any}", + "default": {} + } + }, + { + "cors_rule": { + "description": "List of maps containing rules for Cross-Origin Resource Sharing.", + "type": "${any}", + "default": [] + } + }, + { + "versioning": { + "description": "Map containing versioning configuration.", + "type": "${map(string)}", + "default": {} + } + }, + { + "logging": { + "description": "Map containing access bucket logging configuration.", + "type": "${any}", + "default": {} + } + }, + { + "access_log_delivery_policy_source_buckets": { + "description": "(Optional) List of S3 bucket ARNs which should be allowed to deliver access logs to this bucket.", + "type": "${list(string)}", + "default": [] + } + }, + { + "access_log_delivery_policy_source_accounts": { + "description": "(Optional) List of AWS Account IDs should be allowed to deliver access logs to this bucket.", + "type": "${list(string)}", + "default": [] + } + }, + { + "access_log_delivery_policy_source_organizations": { + "description": "(Optional) List of AWS Organization IDs should be allowed to deliver access logs to this bucket.", + "type": "${list(string)}", + "default": [] + } + }, + { + "lb_log_delivery_policy_source_organizations": { + "description": "(Optional) List of AWS Organization IDs should be allowed to deliver ALB/NLB logs to this bucket.", + "type": "${list(string)}", + "default": [] + } + }, + { + "grant": { + "description": "An ACL policy grant. Conflicts with `acl`", + "type": "${any}", + "default": [] + } + }, + { + "owner": { + "description": "Bucket owner's display name and ID. Conflicts with `acl`", + "type": "${map(string)}", + "default": {} + } + }, + { + "expected_bucket_owner": { + "description": "The account ID of the expected bucket owner", + "type": "${string}", + "default": null + } + }, + { + "transition_default_minimum_object_size": { + "description": "The default minimum object size behavior applied to the lifecycle configuration. Valid values: all_storage_classes_128K (default), varies_by_storage_class", + "type": "${string}", + "default": null + } + }, + { + "lifecycle_rule": { + "description": "List of maps containing configuration of object lifecycle management.", + "type": "${any}", + "default": [] + } + }, + { + "replication_configuration": { + "description": "Map containing cross-region replication configuration.", + "type": "${any}", + "default": {} + } + }, + { + "server_side_encryption_configuration": { + "description": "Map containing server-side encryption configuration.", + "type": "${any}", + "default": {} + } + }, + { + "intelligent_tiering": { + "description": "Map containing intelligent tiering configuration.", + "type": "${any}", + "default": {} + } + }, + { + "object_lock_configuration": { + "description": "Map containing S3 object locking configuration.", + "type": "${any}", + "default": {} + } + }, + { + "metric_configuration": { + "description": "Map containing bucket metric configuration.", + "type": "${any}", + "default": [] + } + }, + { + "inventory_configuration": { + "description": "Map containing S3 inventory configuration.", + "type": "${any}", + "default": {} + } + }, + { + "inventory_source_account_id": { + "description": "The inventory source account id.", + "type": "${string}", + "default": null + } + }, + { + "inventory_source_bucket_arn": { + "description": "The inventory source bucket ARN.", + "type": "${string}", + "default": null + } + }, + { + "inventory_self_source_destination": { + "description": "Whether or not the inventory source bucket is also the destination bucket.", + "type": "${bool}", + "default": false + } + }, + { + "analytics_configuration": { + "description": "Map containing bucket analytics configuration.", + "type": "${any}", + "default": {} + } + }, + { + "analytics_source_account_id": { + "description": "The analytics source account id.", + "type": "${string}", + "default": null + } + }, + { + "analytics_source_bucket_arn": { + "description": "The analytics source bucket ARN.", + "type": "${string}", + "default": null + } + }, + { + "analytics_self_source_destination": { + "description": "Whether or not the analytics source bucket is also the destination bucket.", + "type": "${bool}", + "default": false + } + }, + { + "object_lock_enabled": { + "description": "Whether S3 bucket should have an Object Lock configuration enabled.", + "type": "${bool}", + "default": false + } + }, + { + "block_public_acls": { + "description": "Whether Amazon S3 should block public ACLs for this bucket.", + "type": "${bool}", + "default": true + } + }, + { + "block_public_policy": { + "description": "Whether Amazon S3 should block public bucket policies for this bucket.", + "type": "${bool}", + "default": true + } + }, + { + "skip_destroy_public_access_block": { + "description": "Whether to skip destroying the S3 Bucket Public Access Block configuration when destroying the bucket. Only used if `public_access_block` is set to true.", + "type": "${bool}", + "default": true + } + }, + { + "ignore_public_acls": { + "description": "Whether Amazon S3 should ignore public ACLs for this bucket.", + "type": "${bool}", + "default": true + } + }, + { + "restrict_public_buckets": { + "description": "Whether Amazon S3 should restrict public bucket policies for this bucket.", + "type": "${bool}", + "default": true + } + }, + { + "control_object_ownership": { + "description": "Whether to manage S3 Bucket Ownership Controls on this bucket.", + "type": "${bool}", + "default": false + } + }, + { + "object_ownership": { + "description": "Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL.", + "type": "${string}", + "default": "BucketOwnerEnforced" + } + }, + { + "is_directory_bucket": { + "description": "If the s3 bucket created is a directory bucket", + "type": "${bool}", + "default": false + } + }, + { + "data_redundancy": { + "description": "Data redundancy. Valid values: `SingleAvailabilityZone`", + "type": "${string}", + "default": null + } + }, + { + "type": { + "description": "Bucket type. Valid values: `Directory`", + "type": "${string}", + "default": "Directory" + } + }, + { + "availability_zone_id": { + "description": "Availability Zone ID or Local Zone ID", + "type": "${string}", + "default": null + } + }, + { + "location_type": { + "description": "Location type. Valid values: `AvailabilityZone` or `LocalZone`", + "type": "${string}", + "default": null + } + }, + { + "create_metadata_configuration": { + "description": "Whether to create metadata configuration resource", + "type": "${bool}", + "default": false + } + }, + { + "metadata_inventory_table_configuration_state": { + "description": "Configuration state of the inventory table, indicating whether the inventory table is enabled or disabled. Valid values: ENABLED, DISABLED", + "type": "${string}", + "default": null + } + }, + { + "metadata_encryption_configuration": { + "description": "Encryption configuration block", + "type": "${any}", + "default": null + } + }, + { + "metadata_journal_table_record_expiration_days": { + "description": "Number of days to retain journal table records", + "type": "${number}", + "default": null + } + }, + { + "metadata_journal_table_record_expiration": { + "description": "Whether journal table record expiration is enabled or disabled. Valid values: ENABLED, DISABLED", + "type": "${string}", + "default": null + } + }, + { + "putin_khuylo": { + "description": "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!", + "type": "${bool}", + "default": true + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/variables.tf": [ + { + "create": { + "description": "Controls if resources should be created (affects nearly all resources)", + "type": "${bool}", + "default": true + } + }, + { + "tags": { + "description": "A map of tags to add to all resources", + "type": "${map(string)}", + "default": {} + } + }, + { + "aliases": { + "description": "Extra CNAMEs (alternate domain names), if any, for this distribution", + "type": "${list(string)}", + "default": null + } + }, + { + "anycast_ip_list_id": { + "description": "ID of the Anycast static IP list that is associated with the distribution", + "type": "${string}", + "default": null + } + }, + { + "comment": { + "description": "Any comments you want to include about the distribution", + "type": "${string}", + "default": null + } + }, + { + "continuous_deployment_policy_id": { + "description": "Identifier of a continuous deployment policy. This argument should only be set on a production distribution", + "type": "${string}", + "default": null + } + }, + { + "custom_error_response": { + "description": "One or more custom error response elements", + "type": "${list(object({'error_caching_min_ttl': '${optional(number)}', 'error_code': '${number}', 'response_code': '${optional(number)}', 'response_page_path': '${optional(string)}'}))}", + "default": null + } + }, + { + "default_cache_behavior": { + "description": "The default cache behavior for this distribution", + "type": "${object({'allowed_methods': \"${optional(list(string), ['GET', 'HEAD', 'OPTIONS'])}\", 'cache_policy_id': '${optional(string)}', 'cache_policy_name': '${optional(string)}', 'cached_methods': \"${optional(list(string), ['GET', 'HEAD'])}\", 'compress': '${optional(bool, True)}', 'default_ttl': '${optional(number)}', 'field_level_encryption_id': '${optional(string)}', 'forwarded_values': '${optional(object({\\'cookies\\': \\'${object({\\\\\\'forward\\\\\\': \\\\\\'${optional(string, \"none\")}\\\\\\', \\\\\\'whitelisted_names\\\\\\': \\\\\\'${optional(list(string))}\\\\\\'})}\\', \\'headers\\': \\'${optional(list(string))}\\', \\'query_string\\': \\'${optional(bool, False)}\\', \\'query_string_cache_keys\\': \\'${optional(list(string))}\\'}), {\\'cookies\\': {\\'forward\\': \\'none\\'}, \\'query_string\\': False})}', 'function_association': \"${optional(map(object({'event_type': '${optional(string)}', 'function_arn': '${optional(string)}', 'function_key': '${optional(string)}'})))}\", 'grpc_config': \"${optional(object({'enabled': '${optional(bool)}'}))}\", 'lambda_function_association': \"${optional(map(object({'event_type': '${optional(string)}', 'include_body': '${optional(bool)}', 'lambda_arn': '${string}'})))}\", 'max_ttl': '${optional(number)}', 'min_ttl': '${optional(number)}', 'origin_request_policy_id': '${optional(string)}', 'origin_request_policy_name': '${optional(string)}', 'realtime_log_config_arn': '${optional(string)}', 'response_headers_policy_id': '${optional(string)}', 'response_headers_policy_name': '${optional(string)}', 'smooth_streaming': '${optional(bool)}', 'target_origin_id': '${string}', 'trusted_key_groups': '${optional(list(string))}', 'trusted_signers': '${optional(list(string))}', 'viewer_protocol_policy': '${optional(string, \"https-only\")}'})}", + "nullable": false + } + }, + { + "default_root_object": { + "description": "The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL", + "type": "${string}", + "default": null + } + }, + { + "enabled": { + "description": "Whether the distribution is enabled to accept end user requests for content", + "type": "${bool}", + "default": true + } + }, + { + "http_version": { + "description": "The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3, and http3. The default is http2", + "type": "${string}", + "default": "http2" + } + }, + { + "is_ipv6_enabled": { + "description": "Whether the IPv6 is enabled for the distribution", + "type": "${bool}", + "default": true + } + }, + { + "logging_config": { + "description": "The logging configuration that controls how logs are written to your distribution (maximum one)", + "type": "${object({'bucket': '${optional(string)}', 'include_cookies': '${optional(bool)}', 'prefix': '${optional(string)}'})}", + "default": null + } + }, + { + "ordered_cache_behavior": { + "description": "An ordered list of cache behaviors resource for this distribution. List from top to bottom in order of precedence. The topmost cache behavior will have precedence 0", + "type": "${list(object({'allowed_methods': \"${optional(list(string), ['GET', 'HEAD', 'OPTIONS'])}\", 'cached_methods': \"${optional(list(string), ['GET', 'HEAD'])}\", 'cache_policy_id': '${optional(string)}', 'cache_policy_name': '${optional(string)}', 'compress': '${optional(bool, True)}', 'default_ttl': '${optional(number)}', 'field_level_encryption_id': '${optional(string)}', 'forwarded_values': '${optional(object({\\'cookies\\': \\'${object({\\\\\\'forward\\\\\\': \\\\\\'${optional(string, \"none\")}\\\\\\', \\\\\\'whitelisted_names\\\\\\': \\\\\\'${optional(list(string))}\\\\\\'})}\\', \\'headers\\': \\'${optional(list(string))}\\', \\'query_string\\': \\'${optional(bool, False)}\\', \\'query_string_cache_keys\\': \\'${optional(list(string))}\\'}), {\\'cookies\\': {\\'forward\\': \\'none\\'}, \\'query_string\\': False})}', 'function_association': \"${optional(map(object({'event_type': '${optional(string)}', 'function_arn': '${optional(string)}', 'function_key': '${optional(string)}'})))}\", 'grpc_config': \"${optional(object({'enabled': '${optional(bool)}'}))}\", 'lambda_function_association': \"${optional(map(object({'event_type': '${optional(string)}', 'include_body': '${optional(bool)}', 'lambda_arn': '${string}'})))}\", 'max_ttl': '${optional(number)}', 'min_ttl': '${optional(number)}', 'origin_request_policy_id': '${optional(string)}', 'origin_request_policy_name': '${optional(string)}', 'path_pattern': '${string}', 'realtime_log_config_arn': '${optional(string)}', 'response_headers_policy_id': '${optional(string)}', 'response_headers_policy_name': '${optional(string)}', 'smooth_streaming': '${optional(bool)}', 'target_origin_id': '${string}', 'trusted_key_groups': '${optional(list(string))}', 'trusted_signers': '${optional(list(string))}', 'viewer_protocol_policy': '${string}'}))}", + "default": [], + "nullable": false + } + }, + { + "origin_group": { + "description": "One or more origin_group for this distribution (multiples allowed)", + "type": "${map(object({'failover_criteria': \"${object({'status_codes': '${list(number)}'})}\", 'member': \"${list(object({'origin_id': '${string}'}))}\", 'origin_id': '${optional(string)}'}))}", + "default": null + } + }, + { + "origin": { + "description": "One or more origins for this distribution (multiples allowed)", + "type": "${map(object({'connection_attempts': '${optional(number)}', 'connection_timeout': '${optional(number)}', 'custom_header': '${optional(map(string))}', 'custom_origin_config': '${optional(object({\\'http_port\\': \\'${number}\\', \\'https_port\\': \\'${number}\\', \\'ip_address_type\\': \\'${optional(string)}\\', \\'origin_keepalive_timeout\\': \\'${optional(number)}\\', \\'origin_read_timeout\\': \\'${optional(number)}\\', \\'origin_protocol_policy\\': \\'${string}\\', \\'origin_ssl_protocols\\': \"${optional(list(string), [\\'TLSv1.2\\'])}\"}))}', 'domain_name': '${string}', 'origin_access_control_key': '${optional(string)}', 'origin_access_control_id': '${optional(string)}', 'origin_id': '${optional(string)}', 'origin_path': '${optional(string)}', 'origin_shield': \"${optional(object({'enabled': '${bool}', 'origin_shield_region': '${optional(string)}'}))}\", 'response_completion_timeout': '${optional(number)}', 'vpc_origin_config': \"${optional(object({'origin_keepalive_timeout': '${optional(number)}', 'origin_read_timeout': '${optional(number)}', 'vpc_origin_id': '${optional(string)}', 'vpc_origin_key': '${optional(string)}'}))}\"}))}", + "default": {}, + "nullable": false + } + }, + { + "price_class": { + "description": "The price class for this distribution. One of `PriceClass_All`, `PriceClass_200`, `PriceClass_100`", + "type": "${string}", + "default": null + } + }, + { + "restrictions": { + "description": "The restrictions configuration for this distribution", + "type": "${object({'geo_restriction': '${object({\\'locations\\': \\'${optional(list(string))}\\', \\'restriction_type\\': \\'${optional(string, \"none\")}\\'})}'})}", + "default": { + "geo_restriction": { + "restriction_type": "none" + } + }, + "nullable": false + } + }, + { + "retain_on_delete": { + "description": "Disables the distribution instead of deleting it when destroying the resource through Terraform. If this is set, the distribution needs to be deleted manually afterwards", + "type": "${bool}", + "default": null + } + }, + { + "staging": { + "description": "Whether the distribution is a staging distribution", + "type": "${bool}", + "default": null + } + }, + { + "viewer_certificate": { + "description": "The SSL configuration for this distribution", + "type": "${object({'acm_certificate_arn': '${optional(string)}', 'cloudfront_default_certificate': '${optional(bool)}', 'iam_certificate_id': '${optional(string)}', 'minimum_protocol_version': '${optional(string, \"TLSv1.2_2025\")}', 'ssl_support_method': '${optional(string)}'})}", + "default": {}, + "nullable": false + } + }, + { + "wait_for_deployment": { + "description": "If enabled, the resource will wait for the distribution status to change from InProgress to Deployed. Setting this to false will skip the process", + "type": "${bool}", + "default": null + } + }, + { + "web_acl_id": { + "description": "If you're using AWS WAF to filter CloudFront requests, the Id of the AWS WAF web ACL that is associated with the distribution. The WAF Web ACL must exist in the WAF Global (CloudFront) region and the credentials configuring this argument must have waf:GetWebACL permissions assigned. If using WAFv2, provide the ARN of the web ACL", + "type": "${string}", + "default": null + } + }, + { + "origin_access_control": { + "description": "Map of CloudFront origin access control", + "type": "${map(object({'description': '${optional(string)}', 'name': '${optional(string)}', 'origin_type': '${string}', 'signing_behavior': '${string}', 'signing_protocol': '${string}'}))}", + "default": { + "s3": { + "origin_type": "s3", + "signing_behavior": "always", + "signing_protocol": "sigv4" + } + } + } + }, + { + "vpc_origin": { + "description": "Map of CloudFront VPC origins", + "type": "${map(object({'arn': '${string}', 'http_port': '${number}', 'https_port': '${number}', 'name': '${optional(string)}', 'origin_protocol_policy': '${string}', 'origin_ssl_protocols': '${object({\\'items\\': \"${optional(list(string), [\\'TLSv1.2\\'])}\", \\'quantity\\': \\'${optional(number, 1)}\\'})}', 'timeouts': \"${optional(object({'create': '${optional(string)}', 'update': '${optional(string)}', 'delete': '${optional(string)}'}))}\", 'tags': '${optional(map(string), {})}'}))}", + "default": null + } + }, + { + "response_headers_policies": { + "description": "Map of CloudFront response headers policies with their configurations", + "type": "${map(object({'name': '${optional(string)}', 'comment': '${optional(string)}', 'cors_config': '${optional(object({\\'access_control_allow_credentials\\': \\'${bool}\\', \\'origin_override\\': \\'${bool}\\', \\'access_control_allow_headers\\': \"${object({\\'items\\': \\'${list(string)}\\'})}\", \\'access_control_allow_methods\\': \"${object({\\'items\\': \\'${list(string)}\\'})}\", \\'access_control_allow_origins\\': \"${object({\\'items\\': \\'${list(string)}\\'})}\", \\'access_control_expose_headers\\': \"${optional(object({\\'items\\': \\'${list(string)}\\'}))}\", \\'access_control_max_age_sec\\': \\'${optional(number)}\\'}))}', 'custom_headers_config': '${optional(object({\\'items\\': \"${list(object({\\'header\\': \\'${string}\\', \\'override\\': \\'${bool}\\', \\'value\\': \\'${string}\\'}))}\"}))}', 'remove_headers_config': '${optional(object({\\'items\\': \"${list(object({\\'header\\': \\'${string}\\'}))}\"}))}', 'security_headers_config': '${optional(object({\\'content_security_policy\\': \"${optional(object({\\'content_security_policy\\': \\'${string}\\', \\'override\\': \\'${bool}\\'}))}\", \\'content_type_options\\': \"${optional(object({\\'override\\': \\'${bool}\\'}))}\", \\'frame_options\\': \"${optional(object({\\'frame_option\\': \\'${string}\\', \\'override\\': \\'${bool}\\'}))}\", \\'referrer_policy\\': \"${optional(object({\\'referrer_policy\\': \\'${string}\\', \\'override\\': \\'${bool}\\'}))}\", \\'strict_transport_security\\': \"${optional(object({\\'access_control_max_age_sec\\': \\'${number}\\', \\'override\\': \\'${bool}\\', \\'include_subdomains\\': \\'${optional(bool)}\\', \\'preload\\': \\'${optional(bool)}\\'}))}\", \\'xss_protection\\': \"${optional(object({\\'mode_block\\': \\'${bool}\\', \\'override\\': \\'${bool}\\', \\'protection\\': \\'${bool}\\', \\'report_uri\\': \\'${optional(string)}\\'}))}\"}))}', 'server_timing_headers_config': \"${optional(object({'enabled': '${bool}', 'sampling_rate': '${number}'}))}\"}))}", + "default": null + } + }, + { + "cloudfront_functions": { + "description": "Map of CloudFront Function configurations. Key is used as default function name if 'name' not specified", + "type": "${map(object({'name': '${optional(string)}', 'runtime': '${optional(string, \"cloudfront-js-2.0\")}', 'comment': '${optional(string)}', 'publish': '${optional(bool)}', 'code': '${string}', 'key_value_store_associations': '${optional(list(string))}'}))}", + "default": null + } + }, + { + "create_monitoring_subscription": { + "description": "If enabled, the resource for monitoring subscription will created", + "type": "${bool}", + "default": false + } + }, + { + "realtime_metrics_subscription_status": { + "description": "A flag that indicates whether additional CloudWatch metrics are enabled for a given CloudFront distribution. Valid values are `Enabled` and `Disabled`", + "type": "${string}", + "default": "Enabled" + } + } + ] + }, + "all_locals": { + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/main.tf": [ + { + "create_bucket": "${var.create_bucket && var.putin_khuylo}", + "create_bucket_acl": "${var.acl != None && var.acl != \"null\" || length(local.grants) > 0}", + "attach_policy": "${var.attach_require_latest_tls_policy || var.attach_access_log_delivery_policy || var.attach_elb_log_delivery_policy || var.attach_lb_log_delivery_policy || var.attach_cloudtrail_log_delivery_policy || var.attach_deny_insecure_transport_policy || var.attach_inventory_destination_policy || var.attach_deny_incorrect_encryption_headers || var.attach_deny_incorrect_kms_key_sse || var.attach_deny_unencrypted_object_uploads || var.attach_deny_ssec_encrypted_object_uploads || var.attach_policy || var.attach_waf_log_delivery_policy}", + "policy_placeholders": { + "_S3_BUCKET_ID_": "${try(var.is_directory_bucket ? aws_s3_directory_bucket.this[0].bucket : aws_s3_bucket.this[0].id, None)}", + "_S3_BUCKET_ARN_": "${try(var.is_directory_bucket ? aws_s3_directory_bucket.this[0].arn : aws_s3_bucket.this[0].arn, None)}", + "_AWS_ACCOUNT_ID_": "${try(data.aws_caller_identity.current.account_id, None)}" + }, + "policy": "${local.create_bucket && local.attach_policy ? replace(replace(replace(data.aws_iam_policy_document.combined[0].json, \"_S3_BUCKET_ID_\", local.policy_placeholders[\"_S3_BUCKET_ID_\"]), \"_S3_BUCKET_ARN_\", local.policy_placeholders[\"_S3_BUCKET_ARN_\"]), \"_AWS_ACCOUNT_ID_\", local.policy_placeholders[\"_AWS_ACCOUNT_ID_\"]) : \"\"}", + "grants": "${try(jsondecode(var.grant), var.grant)}", + "cors_rules": "${try(jsondecode(var.cors_rule), var.cors_rule)}", + "lifecycle_rules": "${try(jsondecode(var.lifecycle_rule), var.lifecycle_rule)}", + "intelligent_tiering": "${try(jsondecode(var.intelligent_tiering), var.intelligent_tiering)}", + "metric_configuration": "${try(jsondecode(var.metric_configuration), var.metric_configuration)}" + }, + { + "elb_service_accounts": { + "us-east-1": "127311923021", + "us-east-2": "033677994240", + "us-west-1": "027434742980", + "us-west-2": "797873946194", + "af-south-1": "098369216593", + "ap-east-1": "754344448648", + "ap-south-1": "718504428378", + "ap-northeast-1": "582318560864", + "ap-northeast-2": "600734575887", + "ap-northeast-3": "383597477331", + "ap-southeast-1": "114774131450", + "ap-southeast-2": "783225319266", + "ap-southeast-3": "589379963580", + "ca-central-1": "985666609251", + "eu-central-1": "054676820928", + "eu-west-1": "156460612806", + "eu-west-2": "652711504416", + "eu-west-3": "009996457667", + "eu-south-1": "635631232127", + "eu-north-1": "897822967062", + "me-south-1": "076674570225", + "sa-east-1": "507241528517", + "us-gov-west-1": "048591011584", + "us-gov-east-1": "190560391635", + "cn-north-1": "638102146993", + "cn-northwest-1": "037604701340" + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/main.tf": [ + { + "cache_behaviors": "${concat(['${var.default_cache_behavior}'], var.ordered_cache_behavior)}" + } + ] + }, + "all_resource": { + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/main.tf": [ + { + "aws_s3_bucket": { + "this": { + "count": "${local.create_bucket && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${var.bucket}", + "bucket_prefix": "${var.bucket_prefix}", + "force_destroy": "${var.force_destroy}", + "object_lock_enabled": "${var.object_lock_enabled}", + "tags": "${var.tags}" + } + } + }, + { + "aws_s3_directory_bucket": { + "this": { + "count": "${local.create_bucket && var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${var.bucket}--${var.availability_zone_id}--x-s3", + "data_redundancy": "${var.data_redundancy}", + "force_destroy": "${var.force_destroy}", + "type": "${var.type}", + "location": [ + { + "name": "${var.availability_zone_id}", + "type": "${var.location_type}" + } + ], + "tags": "${var.tags}" + } + } + }, + { + "aws_s3_bucket_logging": { + "this": { + "count": "${local.create_bucket && length(keys(var.logging)) > 0 && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "target_bucket": "${var.logging[\"target_bucket\"]}", + "target_prefix": "${var.logging[\"target_prefix\"]}", + "dynamic": [ + { + "target_object_key_format": { + "for_each": "${try(['${var.logging[\"target_object_key_format\"]}'], [])}", + "content": [ + { + "dynamic": [ + { + "partitioned_prefix": { + "for_each": "${try(target_object_key_format.value[\"partitioned_prefix\"], [])}", + "content": [ + { + "partition_date_source": "${try(partitioned_prefix.value, None)}" + } + ] + } + }, + { + "simple_prefix": { + "for_each": "${length(try(target_object_key_format.value[\"partitioned_prefix\"], [])) == 0 || can(target_object_key_format.value[\"simple_prefix\"]) ? [True] : []}", + "content": [ + {} + ] + } + } + ] + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_acl": { + "this": { + "count": "${local.create_bucket && local.create_bucket_acl && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "acl": "${var.acl == \"null\" ? None : var.acl}", + "dynamic": [ + { + "access_control_policy": { + "for_each": "${length(local.grants) > 0 ? [True] : []}", + "content": [ + { + "dynamic": [ + { + "grant": { + "for_each": "${local.grants}", + "content": [ + { + "permission": "${grant.value.permission}", + "grantee": [ + { + "type": "${grant.value.type}", + "id": "${try(grant.value.id, None)}", + "uri": "${try(grant.value.uri, None)}", + "email_address": "${try(grant.value.email, None)}" + } + ] + } + ] + } + } + ], + "owner": [ + { + "id": "${try(var.owner[\"id\"], data.aws_canonical_user_id.this[0].id)}", + "display_name": "${try(var.owner[\"display_name\"], None)}" + } + ] + } + ] + } + } + ], + "depends_on": [ + "${aws_s3_bucket_ownership_controls.this}" + ] + } + } + }, + { + "aws_s3_bucket_website_configuration": { + "this": { + "count": "${local.create_bucket && length(keys(var.website)) > 0 && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "dynamic": [ + { + "index_document": { + "for_each": "${try(['${var.website[\"index_document\"]}'], [])}", + "content": [ + { + "suffix": "${index_document.value}" + } + ] + } + }, + { + "error_document": { + "for_each": "${try(['${var.website[\"error_document\"]}'], [])}", + "content": [ + { + "key": "${error_document.value}" + } + ] + } + }, + { + "redirect_all_requests_to": { + "for_each": "${try(['${var.website[\"redirect_all_requests_to\"]}'], [])}", + "content": [ + { + "host_name": "${redirect_all_requests_to.value.host_name}", + "protocol": "${try(redirect_all_requests_to.value.protocol, None)}" + } + ] + } + }, + { + "routing_rule": { + "for_each": "${try(flatten(['${var.website[\"routing_rules\"]}']), [])}", + "content": [ + { + "dynamic": [ + { + "condition": { + "for_each": "${try(['${routing_rule.value.condition}'], [])}", + "content": [ + { + "http_error_code_returned_equals": "${try(routing_rule.value.condition[\"http_error_code_returned_equals\"], None)}", + "key_prefix_equals": "${try(routing_rule.value.condition[\"key_prefix_equals\"], None)}" + } + ] + } + } + ], + "redirect": [ + { + "host_name": "${try(routing_rule.value.redirect[\"host_name\"], None)}", + "http_redirect_code": "${try(routing_rule.value.redirect[\"http_redirect_code\"], None)}", + "protocol": "${try(routing_rule.value.redirect[\"protocol\"], None)}", + "replace_key_prefix_with": "${try(routing_rule.value.redirect[\"replace_key_prefix_with\"], None)}", + "replace_key_with": "${try(routing_rule.value.redirect[\"replace_key_with\"], None)}" + } + ] + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_versioning": { + "this": { + "count": "${local.create_bucket && length(keys(var.versioning)) > 0 && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "mfa": "${try(var.versioning[\"mfa\"], None)}", + "versioning_configuration": [ + { + "status": "${try(var.versioning[\"enabled\"] ? \"Enabled\" : \"Suspended\", tobool(var.versioning[\"status\"]) ? \"Enabled\" : \"Suspended\", title(lower(var.versioning[\"status\"])), \"Enabled\")}", + "mfa_delete": "${try(tobool(var.versioning[\"mfa_delete\"]) ? \"Enabled\" : \"Disabled\", title(lower(var.versioning[\"mfa_delete\"])), None)}" + } + ] + } + } + }, + { + "aws_s3_bucket_server_side_encryption_configuration": { + "this": { + "count": "${local.create_bucket && length(keys(var.server_side_encryption_configuration)) > 0 ? 1 : 0}", + "region": "${var.region}", + "bucket": "${var.is_directory_bucket ? aws_s3_directory_bucket.this[0].bucket : aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "dynamic": [ + { + "rule": { + "for_each": "${try(flatten(['${var.server_side_encryption_configuration[\"rule\"]}']), [])}", + "content": [ + { + "bucket_key_enabled": "${try(rule.value.bucket_key_enabled, None)}", + "dynamic": [ + { + "apply_server_side_encryption_by_default": { + "for_each": "${try(['${rule.value.apply_server_side_encryption_by_default}'], [])}", + "content": [ + { + "sse_algorithm": "${apply_server_side_encryption_by_default.value.sse_algorithm}", + "kms_master_key_id": "${try(apply_server_side_encryption_by_default.value.kms_master_key_id, None)}" + } + ] + } + } + ], + "blocked_encryption_types": "${try(rule.value.blocked_encryption_types, None)}" + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_accelerate_configuration": { + "this": { + "count": "${local.create_bucket && var.acceleration_status != None && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "status": "${title(lower(var.acceleration_status))}" + } + } + }, + { + "aws_s3_bucket_request_payment_configuration": { + "this": { + "count": "${local.create_bucket && var.request_payer != None && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "payer": "${lower(var.request_payer) == \"requester\" ? \"Requester\" : \"BucketOwner\"}" + } + } + }, + { + "aws_s3_bucket_cors_configuration": { + "this": { + "count": "${local.create_bucket && length(local.cors_rules) > 0 && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "dynamic": [ + { + "cors_rule": { + "for_each": "${local.cors_rules}", + "content": [ + { + "id": "${try(cors_rule.value.id, None)}", + "allowed_methods": "${cors_rule.value.allowed_methods}", + "allowed_origins": "${cors_rule.value.allowed_origins}", + "allowed_headers": "${try(cors_rule.value.allowed_headers, None)}", + "expose_headers": "${try(cors_rule.value.expose_headers, None)}", + "max_age_seconds": "${try(cors_rule.value.max_age_seconds, None)}" + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_lifecycle_configuration": { + "this": { + "count": "${local.create_bucket && length(local.lifecycle_rules) > 0 ? 1 : 0}", + "region": "${var.region}", + "bucket": "${var.is_directory_bucket ? aws_s3_directory_bucket.this[0].bucket : aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "transition_default_minimum_object_size": "${var.transition_default_minimum_object_size}", + "dynamic": [ + { + "rule": { + "for_each": "${local.lifecycle_rules}", + "content": [ + { + "id": "${try(rule.value.id, None)}", + "status": "${try(rule.value.enabled ? \"Enabled\" : \"Disabled\", tobool(rule.value.status) ? \"Enabled\" : \"Disabled\", title(lower(rule.value.status)))}", + "dynamic": [ + { + "abort_incomplete_multipart_upload": { + "for_each": "${try(['${rule.value.abort_incomplete_multipart_upload_days}'], [])}", + "content": [ + { + "days_after_initiation": "${try(rule.value.abort_incomplete_multipart_upload_days, None)}" + } + ] + } + }, + { + "expiration": { + "for_each": "${try(flatten(['${rule.value.expiration}']), [])}", + "content": [ + { + "date": "${try(expiration.value.date, None)}", + "days": "${try(expiration.value.days, None)}", + "expired_object_delete_marker": "${try(expiration.value.expired_object_delete_marker, None)}" + } + ] + } + }, + { + "transition": { + "for_each": "${try(flatten(['${rule.value.transition}']), [])}", + "content": [ + { + "date": "${try(transition.value.date, None)}", + "days": "${try(transition.value.days, None)}", + "storage_class": "${transition.value.storage_class}" + } + ] + } + }, + { + "noncurrent_version_expiration": { + "for_each": "${try(flatten(['${rule.value.noncurrent_version_expiration}']), [])}", + "content": [ + { + "newer_noncurrent_versions": "${try(noncurrent_version_expiration.value.newer_noncurrent_versions, None)}", + "noncurrent_days": "${try(noncurrent_version_expiration.value.days, noncurrent_version_expiration.value.noncurrent_days, None)}" + } + ] + } + }, + { + "noncurrent_version_transition": { + "for_each": "${try(flatten(['${rule.value.noncurrent_version_transition}']), [])}", + "content": [ + { + "newer_noncurrent_versions": "${try(noncurrent_version_transition.value.newer_noncurrent_versions, None)}", + "noncurrent_days": "${try(noncurrent_version_transition.value.days, noncurrent_version_transition.value.noncurrent_days, None)}", + "storage_class": "${noncurrent_version_transition.value.storage_class}" + } + ] + } + }, + { + "filter": { + "for_each": "${length(try(flatten(['${rule.value.filter}']), [])) == 0 ? [True] : []}", + "content": [ + {} + ] + } + }, + { + "filter": { + "for_each": "${[for v in try(flatten(['${rule.value.filter}']), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) == 1]}", + "content": [ + { + "object_size_greater_than": "${try(filter.value.object_size_greater_than, None)}", + "object_size_less_than": "${try(filter.value.object_size_less_than, None)}", + "prefix": "${try(filter.value.prefix, None)}", + "dynamic": [ + { + "tag": { + "for_each": "${try(filter.value.tags, filter.value.tag, [])}", + "content": [ + { + "key": "${tag.key}", + "value": "${tag.value}" + } + ] + } + } + ] + } + ] + } + }, + { + "filter": { + "for_each": "${[for v in try(flatten(['${rule.value.filter}']), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) > 1]}", + "content": [ + { + "and": [ + { + "object_size_greater_than": "${try(filter.value.object_size_greater_than, None)}", + "object_size_less_than": "${try(filter.value.object_size_less_than, None)}", + "prefix": "${try(filter.value.prefix, None)}", + "tags": "${try(filter.value.tags, filter.value.tag, None)}" + } + ] + } + ] + } + } + ] + } + ] + } + } + ], + "depends_on": [ + "${aws_s3_bucket_versioning.this}", + "${aws_s3_bucket_replication_configuration.this}" + ] + } + } + }, + { + "aws_s3_bucket_object_lock_configuration": { + "this": { + "count": "${local.create_bucket && var.object_lock_enabled && try(var.object_lock_configuration.rule.default_retention, None) != None ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "expected_bucket_owner": "${var.expected_bucket_owner}", + "token": "${try(var.object_lock_configuration.token, None)}", + "rule": [ + { + "default_retention": [ + { + "mode": "${var.object_lock_configuration.rule.default_retention.mode}", + "days": "${try(var.object_lock_configuration.rule.default_retention.days, None)}", + "years": "${try(var.object_lock_configuration.rule.default_retention.years, None)}" + } + ] + } + ] + } + } + }, + { + "aws_s3_bucket_replication_configuration": { + "this": { + "count": "${local.create_bucket && length(keys(var.replication_configuration)) > 0 && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "role": "${var.replication_configuration[\"role\"]}", + "dynamic": [ + { + "rule": { + "for_each": "${flatten(try(['${var.replication_configuration[\"rule\"]}'], ['${var.replication_configuration[\"rules\"]}'], []))}", + "content": [ + { + "id": "${try(rule.value.id, None)}", + "priority": "${try(rule.value.priority, None)}", + "status": "${try(tobool(rule.value.status) ? \"Enabled\" : \"Disabled\", title(lower(rule.value.status)), \"Enabled\")}", + "dynamic": [ + { + "delete_marker_replication": { + "for_each": "${flatten(try(['${rule.value.delete_marker_replication_status}'], ['${rule.value.delete_marker_replication}'], []))}", + "content": [ + { + "status": "${try(tobool(delete_marker_replication.value) ? \"Enabled\" : \"Disabled\", title(lower(delete_marker_replication.value)))}" + } + ] + } + }, + { + "existing_object_replication": { + "for_each": "${flatten(try(['${rule.value.existing_object_replication_status}'], ['${rule.value.existing_object_replication}'], []))}", + "content": [ + { + "status": "${try(tobool(existing_object_replication.value) ? \"Enabled\" : \"Disabled\", title(lower(existing_object_replication.value)))}" + } + ] + } + }, + { + "destination": { + "for_each": "${try(flatten(['${rule.value.destination}']), [])}", + "content": [ + { + "bucket": "${destination.value.bucket}", + "storage_class": "${try(destination.value.storage_class, None)}", + "account": "${try(destination.value.account_id, destination.value.account, None)}", + "dynamic": [ + { + "access_control_translation": { + "for_each": "${try(flatten(['${destination.value.access_control_translation}']), [])}", + "content": [ + { + "owner": "${title(lower(access_control_translation.value.owner))}" + } + ] + } + }, + { + "encryption_configuration": { + "for_each": "${flatten(['${try(destination.value.encryption_configuration.replica_kms_key_id, destination.value.replica_kms_key_id, [])}'])}", + "content": [ + { + "replica_kms_key_id": "${encryption_configuration.value}" + } + ] + } + }, + { + "replication_time": { + "for_each": "${try(flatten(['${destination.value.replication_time}']), [])}", + "content": [ + { + "status": "${try(tobool(replication_time.value.status) ? \"Enabled\" : \"Disabled\", title(lower(replication_time.value.status)), \"Disabled\")}", + "dynamic": [ + { + "time": { + "for_each": "${try(flatten(['${replication_time.value.minutes}']), [])}", + "content": [ + { + "minutes": "${replication_time.value.minutes}" + } + ] + } + } + ] + } + ] + } + }, + { + "metrics": { + "for_each": "${try(flatten(['${destination.value.metrics}']), [])}", + "content": [ + { + "status": "${try(tobool(metrics.value.status) ? \"Enabled\" : \"Disabled\", title(lower(metrics.value.status)), \"Disabled\")}", + "dynamic": [ + { + "event_threshold": { + "for_each": "${try(flatten(['${metrics.value.minutes}']), [])}", + "content": [ + { + "minutes": "${metrics.value.minutes}" + } + ] + } + } + ] + } + ] + } + } + ] + } + ] + } + }, + { + "source_selection_criteria": { + "for_each": "${try(flatten(['${rule.value.source_selection_criteria}']), [])}", + "content": [ + { + "dynamic": [ + { + "replica_modifications": { + "for_each": "${flatten(['${try(source_selection_criteria.value.replica_modifications.enabled, source_selection_criteria.value.replica_modifications.status, [])}'])}", + "content": [ + { + "status": "${try(tobool(replica_modifications.value) ? \"Enabled\" : \"Disabled\", title(lower(replica_modifications.value)), \"Disabled\")}" + } + ] + } + }, + { + "sse_kms_encrypted_objects": { + "for_each": "${flatten(['${try(source_selection_criteria.value.sse_kms_encrypted_objects.enabled, source_selection_criteria.value.sse_kms_encrypted_objects.status, [])}'])}", + "content": [ + { + "status": "${try(tobool(sse_kms_encrypted_objects.value) ? \"Enabled\" : \"Disabled\", title(lower(sse_kms_encrypted_objects.value)), \"Disabled\")}" + } + ] + } + } + ] + } + ] + } + }, + { + "filter": { + "for_each": "${length(try(flatten(['${rule.value.filter}']), [])) == 0 ? [True] : []}", + "content": [ + {} + ] + } + }, + { + "filter": { + "for_each": "${[for v in try(flatten(['${rule.value.filter}']), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) == 1]}", + "content": [ + { + "prefix": "${try(filter.value.prefix, None)}", + "dynamic": [ + { + "tag": { + "for_each": "${try(filter.value.tags, filter.value.tag, [])}", + "content": [ + { + "key": "${tag.key}", + "value": "${tag.value}" + } + ] + } + } + ] + } + ] + } + }, + { + "filter": { + "for_each": "${[for v in try(flatten(['${rule.value.filter}']), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) > 1]}", + "content": [ + { + "and": [ + { + "prefix": "${try(filter.value.prefix, None)}", + "tags": "${try(filter.value.tags, filter.value.tag, None)}" + } + ] + } + ] + } + } + ] + } + ] + } + } + ], + "depends_on": [ + "${aws_s3_bucket_versioning.this}" + ] + } + } + }, + { + "aws_s3_bucket_policy": { + "this": { + "count": "${local.create_bucket && local.attach_policy ? 1 : 0}", + "region": "${var.region}", + "bucket": "${var.is_directory_bucket ? aws_s3_directory_bucket.this[0].bucket : aws_s3_bucket.this[0].id}", + "policy": "${local.policy}", + "depends_on": [ + "${aws_s3_bucket_public_access_block.this}" + ] + } + } + }, + { + "aws_s3_bucket_public_access_block": { + "this": { + "count": "${local.create_bucket && var.attach_public_policy && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "block_public_acls": "${var.block_public_acls}", + "block_public_policy": "${var.block_public_policy}", + "ignore_public_acls": "${var.ignore_public_acls}", + "restrict_public_buckets": "${var.restrict_public_buckets}", + "skip_destroy": "${var.skip_destroy_public_access_block}" + } + } + }, + { + "aws_s3_bucket_ownership_controls": { + "this": { + "count": "${local.create_bucket && var.control_object_ownership && !var.is_directory_bucket ? 1 : 0}", + "region": "${var.region}", + "bucket": "${local.attach_policy ? aws_s3_bucket_policy.this[0].id : aws_s3_bucket.this[0].id}", + "rule": [ + { + "object_ownership": "${var.object_ownership}" + } + ], + "depends_on": [ + "${aws_s3_bucket_policy.this}", + "${aws_s3_bucket_public_access_block.this}", + "${aws_s3_bucket.this}" + ] + } + } + }, + { + "aws_s3_bucket_intelligent_tiering_configuration": { + "this": { + "for_each": "${{for k , v in local.intelligent_tiering : k => v if local.create_bucket && !var.is_directory_bucket}}", + "region": "${var.region}", + "name": "${each.key}", + "bucket": "${aws_s3_bucket.this[0].id}", + "status": "${try(tobool(each.value.status) ? \"Enabled\" : \"Disabled\", title(lower(each.value.status)), None)}", + "dynamic": [ + { + "filter": { + "for_each": "${length(try(flatten(['${each.value.filter}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "prefix": "${try(each.value.filter.prefix, None)}", + "tags": "${try(each.value.filter.tags, None)}" + } + ] + } + }, + { + "tiering": { + "for_each": "${each.value.tiering}", + "content": [ + { + "access_tier": "${tiering.key}", + "days": "${tiering.value.days}" + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_metric": { + "this": { + "for_each": "${{for k , v in local.metric_configuration : k => v if local.create_bucket && !var.is_directory_bucket}}", + "region": "${var.region}", + "name": "${each.value.name}", + "bucket": "${aws_s3_bucket.this[0].id}", + "dynamic": [ + { + "filter": { + "for_each": "${length(try(flatten(['${each.value.filter}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "prefix": "${try(each.value.filter.prefix, None)}", + "tags": "${try(each.value.filter.tags, None)}" + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_inventory": { + "this": { + "for_each": "${{for k , v in var.inventory_configuration : k => v if local.create_bucket && !var.is_directory_bucket}}", + "region": "${var.region}", + "name": "${each.key}", + "bucket": "${try(each.value.bucket, aws_s3_bucket.this[0].id)}", + "included_object_versions": "${each.value.included_object_versions}", + "enabled": "${try(each.value.enabled, True)}", + "optional_fields": "${try(each.value.optional_fields, None)}", + "destination": [ + { + "bucket": [ + { + "bucket_arn": "${try(each.value.destination.bucket_arn, aws_s3_bucket.this[0].arn)}", + "format": "${try(each.value.destination.format, None)}", + "account_id": "${try(each.value.destination.account_id, None)}", + "prefix": "${try(each.value.destination.prefix, None)}", + "dynamic": [ + { + "encryption": { + "for_each": "${length(try(flatten(['${each.value.destination.encryption}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "dynamic": [ + { + "sse_kms": { + "for_each": "${each.value.destination.encryption.encryption_type == \"sse_kms\" ? [True] : []}", + "content": [ + { + "key_id": "${try(each.value.destination.encryption.kms_key_id, None)}" + } + ] + } + }, + { + "sse_s3": { + "for_each": "${each.value.destination.encryption.encryption_type == \"sse_s3\" ? [True] : []}", + "content": [ + {} + ] + } + } + ] + } + ] + } + } + ] + } + ] + } + ], + "schedule": [ + { + "frequency": "${each.value.frequency}" + } + ], + "dynamic": [ + { + "filter": { + "for_each": "${length(try(flatten(['${each.value.filter}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "prefix": "${try(each.value.filter.prefix, None)}" + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_analytics_configuration": { + "this": { + "for_each": "${{for k , v in var.analytics_configuration : k => v if local.create_bucket && !var.is_directory_bucket}}", + "region": "${var.region}", + "bucket": "${aws_s3_bucket.this[0].id}", + "name": "${each.key}", + "dynamic": [ + { + "filter": { + "for_each": "${length(try(flatten(['${each.value.filter}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "prefix": "${try(each.value.filter.prefix, None)}", + "tags": "${try(each.value.filter.tags, None)}" + } + ] + } + }, + { + "storage_class_analysis": { + "for_each": "${length(try(flatten(['${each.value.storage_class_analysis}']), [])) == 0 ? [] : [True]}", + "content": [ + { + "data_export": [ + { + "output_schema_version": "${try(each.value.storage_class_analysis.output_schema_version, None)}", + "destination": [ + { + "s3_bucket_destination": [ + { + "bucket_arn": "${try(each.value.storage_class_analysis.destination_bucket_arn, aws_s3_bucket.this[0].arn)}", + "bucket_account_id": "${try(each.value.storage_class_analysis.destination_account_id, data.aws_caller_identity.current.id)}", + "format": "${try(each.value.storage_class_analysis.export_format, \"CSV\")}", + "prefix": "${try(each.value.storage_class_analysis.export_prefix, None)}" + } + ] + } + ] + } + ] + } + ] + } + } + ] + } + } + }, + { + "aws_s3_bucket_metadata_configuration": { + "this": { + "count": "${local.create_bucket && var.create_metadata_configuration ? 1 : 0}", + "bucket": "${aws_s3_bucket.this[0].bucket}", + "region": "${var.region}", + "metadata_configuration": [ + { + "inventory_table_configuration": [ + { + "configuration_state": "${var.metadata_inventory_table_configuration_state}", + "dynamic": [ + { + "encryption_configuration": { + "for_each": "${var.metadata_encryption_configuration != None ? ['${var.metadata_encryption_configuration}'] : []}", + "content": [ + { + "kms_key_arn": "${try(encryption_configuration.value.kms_key_arn, None)}", + "sse_algorithm": "${encryption_configuration.value.sse_algorithm}" + } + ] + } + } + ] + } + ], + "journal_table_configuration": [ + { + "record_expiration": [ + { + "days": "${var.metadata_journal_table_record_expiration_days}", + "expiration": "${var.metadata_journal_table_record_expiration}" + } + ] + } + ] + } + ] + } + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/main.tf": [ + { + "aws_cloudfront_distribution": { + "this": { + "count": "${var.create ? 1 : 0}", + "aliases": "${var.aliases}", + "anycast_ip_list_id": "${var.anycast_ip_list_id}", + "comment": "${var.comment}", + "continuous_deployment_policy_id": "${var.continuous_deployment_policy_id}", + "dynamic": [ + { + "custom_error_response": { + "for_each": "${var.custom_error_response != None ? var.custom_error_response : []}", + "content": [ + { + "error_caching_min_ttl": "${custom_error_response.value.error_caching_min_ttl}", + "error_code": "${custom_error_response.value.error_code}", + "response_code": "${custom_error_response.value.response_code}", + "response_page_path": "${custom_error_response.value.response_page_path}" + } + ] + } + }, + { + "default_cache_behavior": { + "for_each": [ + "${var.default_cache_behavior}" + ], + "content": [ + { + "allowed_methods": "${default_cache_behavior.value.allowed_methods}", + "cache_policy_id": "${try(coalesce(default_cache_behavior.value.cache_policy_id, try(data.aws_cloudfront_cache_policy.this[default_cache_behavior.value.cache_policy_name].id, None)), None)}", + "cached_methods": "${default_cache_behavior.value.cached_methods}", + "compress": "${default_cache_behavior.value.compress}", + "default_ttl": "${default_cache_behavior.value.default_ttl}", + "field_level_encryption_id": "${default_cache_behavior.value.field_level_encryption_id}", + "dynamic": [ + { + "forwarded_values": { + "for_each": "${default_cache_behavior.value.cache_policy_id == None && default_cache_behavior.value.cache_policy_name == None && default_cache_behavior.value.forwarded_values != None ? ['${default_cache_behavior.value.forwarded_values}'] : []}", + "content": [ + { + "dynamic": [ + { + "cookies": { + "for_each": [ + "${forwarded_values.value.cookies}" + ], + "content": [ + { + "forward": "${cookies.value.forward}", + "whitelisted_names": "${cookies.value.whitelisted_names}" + } + ] + } + } + ], + "headers": "${forwarded_values.value.headers}", + "query_string": "${forwarded_values.value.query_string}", + "query_string_cache_keys": "${forwarded_values.value.query_string_cache_keys}" + } + ] + } + }, + { + "function_association": { + "for_each": "${default_cache_behavior.value.function_association != None ? default_cache_behavior.value.function_association : {}}", + "content": [ + { + "event_type": "${try(coalesce(function_association.value.event_type, function_association.key))}", + "function_arn": "${try(coalesce(function_association.value.function_arn, try(aws_cloudfront_function.this[function_association.value.function_key].arn, None)), None)}" + } + ] + } + }, + { + "grpc_config": { + "for_each": "${default_cache_behavior.value.grpc_config != None ? ['${default_cache_behavior.value.grpc_config}'] : []}", + "content": [ + { + "enabled": "${grpc_config.value.enabled}" + } + ] + } + }, + { + "lambda_function_association": { + "for_each": "${default_cache_behavior.value.lambda_function_association != None ? default_cache_behavior.value.lambda_function_association : {}}", + "content": [ + { + "event_type": "${try(coalesce(lambda_function_association.value.event_type, lambda_function_association.key))}", + "include_body": "${lambda_function_association.value.include_body}", + "lambda_arn": "${lambda_function_association.value.lambda_arn}" + } + ] + } + } + ], + "max_ttl": "${default_cache_behavior.value.max_ttl}", + "min_ttl": "${default_cache_behavior.value.min_ttl}", + "origin_request_policy_id": "${try(coalesce(default_cache_behavior.value.origin_request_policy_id, try(data.aws_cloudfront_origin_request_policy.this[default_cache_behavior.value.origin_request_policy_name].id, None)), None)}", + "realtime_log_config_arn": "${default_cache_behavior.value.realtime_log_config_arn}", + "response_headers_policy_id": "${try(coalesce(default_cache_behavior.value.response_headers_policy_id, try(data.aws_cloudfront_response_headers_policy.this[default_cache_behavior.value.response_headers_policy_name].id, None)), None)}", + "smooth_streaming": "${default_cache_behavior.value.smooth_streaming}", + "target_origin_id": "${default_cache_behavior.value.target_origin_id}", + "trusted_key_groups": "${default_cache_behavior.value.trusted_key_groups}", + "trusted_signers": "${default_cache_behavior.value.trusted_signers}", + "viewer_protocol_policy": "${default_cache_behavior.value.viewer_protocol_policy}" + } + ] + } + }, + { + "logging_config": { + "for_each": "${var.logging_config != None ? ['${var.logging_config}'] : []}", + "content": [ + { + "bucket": "${logging_config.value.bucket}", + "include_cookies": "${logging_config.value.include_cookies}", + "prefix": "${logging_config.value.prefix}" + } + ] + } + }, + { + "ordered_cache_behavior": { + "for_each": "${length(var.ordered_cache_behavior) > 0 ? var.ordered_cache_behavior : []}", + "content": [ + { + "allowed_methods": "${ordered_cache_behavior.value.allowed_methods}", + "cached_methods": "${ordered_cache_behavior.value.cached_methods}", + "cache_policy_id": "${try(coalesce(ordered_cache_behavior.value.cache_policy_id, try(data.aws_cloudfront_cache_policy.this[ordered_cache_behavior.value.cache_policy_name].id, None)), None)}", + "compress": "${ordered_cache_behavior.value.compress}", + "default_ttl": "${ordered_cache_behavior.value.default_ttl}", + "field_level_encryption_id": "${ordered_cache_behavior.value.field_level_encryption_id}", + "dynamic": [ + { + "forwarded_values": { + "for_each": "${ordered_cache_behavior.value.cache_policy_id == None && ordered_cache_behavior.value.cache_policy_name == None && ordered_cache_behavior.value.forwarded_values != None ? ['${ordered_cache_behavior.value.forwarded_values}'] : []}", + "content": [ + { + "dynamic": [ + { + "cookies": { + "for_each": [ + "${forwarded_values.value.cookies}" + ], + "content": [ + { + "forward": "${cookies.value.forward}", + "whitelisted_names": "${cookies.value.whitelisted_names}" + } + ] + } + } + ], + "headers": "${forwarded_values.value.headers}", + "query_string": "${forwarded_values.value.query_string}", + "query_string_cache_keys": "${forwarded_values.value.query_string_cache_keys}" + } + ] + } + }, + { + "function_association": { + "for_each": "${ordered_cache_behavior.value.function_association != None ? ordered_cache_behavior.value.function_association : {}}", + "content": [ + { + "event_type": "${try(coalesce(function_association.value.event_type, function_association.key))}", + "function_arn": "${try(coalesce(function_association.value.function_arn, try(aws_cloudfront_function.this[function_association.value.function_key].arn, None)), None)}" + } + ] + } + }, + { + "grpc_config": { + "for_each": "${ordered_cache_behavior.value.grpc_config != None ? ['${ordered_cache_behavior.value.grpc_config}'] : []}", + "content": [ + { + "enabled": "${grpc_config.value.enabled}" + } + ] + } + }, + { + "lambda_function_association": { + "for_each": "${ordered_cache_behavior.value.lambda_function_association != None ? ordered_cache_behavior.value.lambda_function_association : {}}", + "content": [ + { + "event_type": "${try(coalesce(lambda_function_association.value.event_type, lambda_function_association.key))}", + "include_body": "${lambda_function_association.value.include_body}", + "lambda_arn": "${lambda_function_association.value.lambda_arn}" + } + ] + } + } + ], + "max_ttl": "${ordered_cache_behavior.value.max_ttl}", + "min_ttl": "${ordered_cache_behavior.value.min_ttl}", + "origin_request_policy_id": "${try(coalesce(ordered_cache_behavior.value.origin_request_policy_id, try(data.aws_cloudfront_origin_request_policy.this[ordered_cache_behavior.value.origin_request_policy_name].id, None)), None)}", + "path_pattern": "${ordered_cache_behavior.value.path_pattern}", + "realtime_log_config_arn": "${ordered_cache_behavior.value.realtime_log_config_arn}", + "response_headers_policy_id": "${try(coalesce(ordered_cache_behavior.value.response_headers_policy_id, try(data.aws_cloudfront_response_headers_policy.this[ordered_cache_behavior.value.response_headers_policy_name].id, None)), None)}", + "smooth_streaming": "${ordered_cache_behavior.value.smooth_streaming}", + "target_origin_id": "${ordered_cache_behavior.value.target_origin_id}", + "trusted_key_groups": "${ordered_cache_behavior.value.trusted_key_groups}", + "trusted_signers": "${ordered_cache_behavior.value.trusted_signers}", + "viewer_protocol_policy": "${ordered_cache_behavior.value.viewer_protocol_policy}" + } + ] + } + }, + { + "origin_group": { + "for_each": "${var.origin_group != None ? var.origin_group : {}}", + "content": [ + { + "dynamic": [ + { + "failover_criteria": { + "for_each": [ + "${origin_group.value.failover_criteria}" + ], + "content": [ + { + "status_codes": "${failover_criteria.value.status_codes}" + } + ] + } + }, + { + "member": { + "for_each": "${origin_group.value.member}", + "content": [ + { + "origin_id": "${member.value.origin_id}" + } + ] + } + } + ], + "origin_id": "${try(coalesce(origin_group.value.origin_id, origin_group.key))}" + } + ] + } + }, + { + "origin": { + "for_each": "${var.origin}", + "content": [ + { + "connection_attempts": "${origin.value.connection_attempts}", + "connection_timeout": "${origin.value.connection_timeout}", + "dynamic": [ + { + "custom_header": { + "for_each": "${origin.value.custom_header != None ? origin.value.custom_header : {}}", + "content": [ + { + "name": "${custom_header.key}", + "value": "${custom_header.value}" + } + ] + } + }, + { + "custom_origin_config": { + "for_each": "${origin.value.custom_origin_config != None ? ['${origin.value.custom_origin_config}'] : []}", + "content": [ + { + "http_port": "${custom_origin_config.value.http_port}", + "https_port": "${custom_origin_config.value.https_port}", + "ip_address_type": "${custom_origin_config.value.ip_address_type}", + "origin_keepalive_timeout": "${custom_origin_config.value.origin_keepalive_timeout}", + "origin_read_timeout": "${custom_origin_config.value.origin_read_timeout}", + "origin_protocol_policy": "${custom_origin_config.value.origin_protocol_policy}", + "origin_ssl_protocols": "${custom_origin_config.value.origin_ssl_protocols}" + } + ] + } + }, + { + "origin_shield": { + "for_each": "${origin.value.origin_shield != None ? ['${origin.value.origin_shield}'] : []}", + "content": [ + { + "enabled": "${origin_shield.value.enabled}", + "origin_shield_region": "${origin_shield.value.origin_shield_region}" + } + ] + } + }, + { + "vpc_origin_config": { + "for_each": "${origin.value.vpc_origin_config != None ? ['${origin.value.vpc_origin_config}'] : []}", + "content": [ + { + "origin_keepalive_timeout": "${vpc_origin_config.value.origin_keepalive_timeout}", + "origin_read_timeout": "${vpc_origin_config.value.origin_read_timeout}", + "vpc_origin_id": "${try(coalesce(vpc_origin_config.value.vpc_origin_id, try(aws_cloudfront_vpc_origin.this[vpc_origin_config.value.vpc_origin_key].id, None)), None)}" + } + ] + } + } + ], + "domain_name": "${origin.value.domain_name}", + "origin_access_control_id": "${try(coalesce(origin.value.origin_access_control_id, try(aws_cloudfront_origin_access_control.this[origin.value.origin_access_control_key].id, None)), None)}", + "origin_id": "${try(coalesce(origin.value.origin_id, origin.key))}", + "origin_path": "${origin.value.origin_path}", + "response_completion_timeout": "${origin.value.response_completion_timeout}" + } + ] + } + }, + { + "restrictions": { + "for_each": [ + "${var.restrictions}" + ], + "content": [ + { + "dynamic": [ + { + "geo_restriction": { + "for_each": [ + "${restrictions.value.geo_restriction}" + ], + "content": [ + { + "restriction_type": "${geo_restriction.value.restriction_type}", + "locations": "${geo_restriction.value.locations}" + } + ] + } + } + ] + } + ] + } + }, + { + "viewer_certificate": { + "for_each": [ + "${var.viewer_certificate}" + ], + "content": [ + { + "acm_certificate_arn": "${viewer_certificate.value.acm_certificate_arn}", + "cloudfront_default_certificate": "${viewer_certificate.value.cloudfront_default_certificate}", + "iam_certificate_id": "${viewer_certificate.value.iam_certificate_id}", + "minimum_protocol_version": "${viewer_certificate.value.minimum_protocol_version}", + "ssl_support_method": "${viewer_certificate.value.ssl_support_method}" + } + ] + } + } + ], + "default_root_object": "${var.default_root_object}", + "enabled": "${var.enabled}", + "http_version": "${var.http_version}", + "is_ipv6_enabled": "${var.is_ipv6_enabled}", + "price_class": "${var.price_class}", + "retain_on_delete": "${var.retain_on_delete}", + "staging": "${var.staging}", + "wait_for_deployment": "${var.wait_for_deployment}", + "web_acl_id": "${var.web_acl_id}", + "tags": "${var.tags}", + "depends_on": [ + "${aws_cloudfront_function.this}" + ] + } + } + }, + { + "aws_cloudfront_origin_access_control": { + "this": { + "for_each": "${var.origin_access_control != None ? var.origin_access_control : {}}", + "description": "${try(coalesce(each.value.description, \"Origin Access Control for ${try(coalesce(each.value.name, each.key))}\"))}", + "name": "${try(coalesce(each.value.name, each.key))}", + "origin_access_control_origin_type": "${each.value.origin_type}", + "signing_behavior": "${each.value.signing_behavior}", + "signing_protocol": "${each.value.signing_protocol}" + } + } + }, + { + "aws_cloudfront_vpc_origin": { + "this": { + "for_each": "${var.vpc_origin != None ? var.vpc_origin : {}}", + "vpc_origin_endpoint_config": [ + { + "arn": "${each.value.arn}", + "http_port": "${each.value.http_port}", + "https_port": "${each.value.https_port}", + "name": "${try(coalesce(each.value.name, each.key))}", + "origin_protocol_policy": "${each.value.origin_protocol_policy}", + "dynamic": [ + { + "origin_ssl_protocols": { + "for_each": "${each.value.origin_ssl_protocols != None ? ['${each.value.origin_ssl_protocols}'] : []}", + "content": [ + { + "items": "${origin_ssl_protocols.value.items}", + "quantity": "${origin_ssl_protocols.value.quantity}" + } + ] + } + } + ] + } + ], + "dynamic": [ + { + "timeouts": { + "for_each": "${each.value.timeouts != None ? ['${each.value.timeouts}'] : []}", + "content": [ + { + "create": "${timeouts.value.create}", + "update": "${timeouts.value.update}", + "delete": "${timeouts.value.delete}" + } + ] + } + } + ], + "tags": "${merge(var.tags, each.value.tags)}" + } + } + }, + { + "aws_cloudfront_response_headers_policy": { + "this": { + "for_each": "${var.response_headers_policies != None ? var.response_headers_policies : {}}", + "name": "${try(coalesce(each.value.name, each.key))}", + "comment": "${each.value.comment}", + "dynamic": [ + { + "cors_config": { + "for_each": "${each.value.cors_config != None ? ['${each.value.cors_config}'] : []}", + "content": [ + { + "access_control_allow_credentials": "${cors_config.value.access_control_allow_credentials}", + "origin_override": "${cors_config.value.origin_override}", + "access_control_max_age_sec": "${cors_config.value.access_control_max_age_sec}", + "access_control_allow_headers": [ + { + "items": "${cors_config.value.access_control_allow_headers.items}" + } + ], + "access_control_allow_methods": [ + { + "items": "${cors_config.value.access_control_allow_methods.items}" + } + ], + "access_control_allow_origins": [ + { + "items": "${cors_config.value.access_control_allow_origins.items}" + } + ], + "dynamic": [ + { + "access_control_expose_headers": { + "for_each": "${cors_config.value.access_control_expose_headers != None ? ['${cors_config.value.access_control_expose_headers}'] : []}", + "content": [ + { + "items": "${access_control_expose_headers.value.items}" + } + ] + } + } + ] + } + ] + } + }, + { + "custom_headers_config": { + "for_each": "${each.value.custom_headers_config != None ? ['${each.value.custom_headers_config}'] : []}", + "content": [ + { + "dynamic": [ + { + "items": { + "for_each": "${custom_headers_config.value.items}", + "content": [ + { + "header": "${items.value.header}", + "override": "${items.value.override}", + "value": "${items.value.value}" + } + ] + } + } + ] + } + ] + } + }, + { + "remove_headers_config": { + "for_each": "${each.value.remove_headers_config != None ? ['${each.value.remove_headers_config}'] : []}", + "content": [ + { + "dynamic": [ + { + "items": { + "for_each": "${remove_headers_config.value.items}", + "content": [ + { + "header": "${items.value.header}" + } + ] + } + } + ] + } + ] + } + }, + { + "security_headers_config": { + "for_each": "${each.value.security_headers_config != None ? ['${each.value.security_headers_config}'] : []}", + "content": [ + { + "dynamic": [ + { + "content_security_policy": { + "for_each": "${security_headers_config.value.content_security_policy != None ? ['${security_headers_config.value.content_security_policy}'] : []}", + "content": [ + { + "content_security_policy": "${content_security_policy.value.content_security_policy}", + "override": "${content_security_policy.value.override}" + } + ] + } + }, + { + "content_type_options": { + "for_each": "${security_headers_config.value.content_type_options != None ? ['${security_headers_config.value.content_type_options}'] : []}", + "content": [ + { + "override": "${content_type_options.value.override}" + } + ] + } + }, + { + "frame_options": { + "for_each": "${security_headers_config.value.frame_options != None ? ['${security_headers_config.value.frame_options}'] : []}", + "content": [ + { + "frame_option": "${frame_options.value.frame_option}", + "override": "${frame_options.value.override}" + } + ] + } + }, + { + "referrer_policy": { + "for_each": "${security_headers_config.value.referrer_policy != None ? ['${security_headers_config.value.referrer_policy}'] : []}", + "content": [ + { + "referrer_policy": "${referrer_policy.value.referrer_policy}", + "override": "${referrer_policy.value.override}" + } + ] + } + }, + { + "strict_transport_security": { + "for_each": "${security_headers_config.value.strict_transport_security != None ? ['${security_headers_config.value.strict_transport_security}'] : []}", + "content": [ + { + "access_control_max_age_sec": "${strict_transport_security.value.access_control_max_age_sec}", + "override": "${strict_transport_security.value.override}", + "include_subdomains": "${strict_transport_security.value.include_subdomains}", + "preload": "${strict_transport_security.value.preload}" + } + ] + } + }, + { + "xss_protection": { + "for_each": "${security_headers_config.value.xss_protection != None ? ['${security_headers_config.value.xss_protection}'] : []}", + "content": [ + { + "mode_block": "${xss_protection.value.mode_block}", + "override": "${xss_protection.value.override}", + "protection": "${xss_protection.value.protection}", + "report_uri": "${xss_protection.value.report_uri}" + } + ] + } + } + ] + } + ] + } + }, + { + "server_timing_headers_config": { + "for_each": "${each.value.server_timing_headers_config != None ? ['${each.value.server_timing_headers_config}'] : []}", + "content": [ + { + "enabled": "${server_timing_headers_config.value.enabled}", + "sampling_rate": "${server_timing_headers_config.value.sampling_rate}" + } + ] + } + } + ] + } + } + }, + { + "aws_cloudfront_function": { + "this": { + "for_each": "${var.cloudfront_functions != None ? var.cloudfront_functions : {}}", + "code": "${each.value.code}", + "comment": "${each.value.comment}", + "key_value_store_associations": "${each.value.key_value_store_associations}", + "name": "${try(coalesce(each.value.name, each.key))}", + "publish": "${each.value.publish}", + "runtime": "${each.value.runtime}" + } + } + }, + { + "aws_cloudfront_monitoring_subscription": { + "this": { + "count": "${var.create && var.create_monitoring_subscription ? 1 : 0}", + "distribution_id": "${aws_cloudfront_distribution.this[0].id}", + "monitoring_subscription": [ + { + "realtime_metrics_subscription_config": [ + { + "realtime_metrics_subscription_status": "${var.realtime_metrics_subscription_status}" + } + ] + } + ] + } + } + } + ] + }, + "all_data": { + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/main.tf": [ + { + "aws_region": { + "current": { + "region": "${var.region}" + } + } + }, + { + "aws_canonical_user_id": { + "this": { + "count": "${local.create_bucket && local.create_bucket_acl && try(var.owner[\"id\"], None) == None ? 1 : 0}" + } + } + }, + { + "aws_caller_identity": { + "current": {} + } + }, + { + "aws_partition": { + "current": {} + } + }, + { + "aws_iam_policy_document": { + "combined": { + "count": "${local.create_bucket && local.attach_policy ? 1 : 0}", + "source_policy_documents": "${compact(['${var.attach_elb_log_delivery_policy ? data.aws_iam_policy_document.elb_log_delivery[0].json : \"\"}', '${var.attach_lb_log_delivery_policy ? data.aws_iam_policy_document.lb_log_delivery[0].json : \"\"}', '${var.attach_access_log_delivery_policy ? data.aws_iam_policy_document.access_log_delivery[0].json : \"\"}', '${var.attach_cloudtrail_log_delivery_policy ? data.aws_iam_policy_document.cloudtrail_log_delivery[0].json : \"\"}', '${var.attach_require_latest_tls_policy ? data.aws_iam_policy_document.require_latest_tls[0].json : \"\"}', '${var.attach_deny_insecure_transport_policy ? data.aws_iam_policy_document.deny_insecure_transport[0].json : \"\"}', '${var.attach_deny_unencrypted_object_uploads ? data.aws_iam_policy_document.deny_unencrypted_object_uploads[0].json : \"\"}', '${var.attach_deny_ssec_encrypted_object_uploads ? data.aws_iam_policy_document.deny_ssec_encrypted_object_uploads[0].json : \"\"}', '${var.attach_deny_incorrect_kms_key_sse ? data.aws_iam_policy_document.deny_incorrect_kms_key_sse[0].json : \"\"}', '${var.attach_deny_incorrect_encryption_headers ? data.aws_iam_policy_document.deny_incorrect_encryption_headers[0].json : \"\"}', '${var.attach_inventory_destination_policy || var.attach_analytics_destination_policy ? data.aws_iam_policy_document.inventory_and_analytics_destination_policy[0].json : \"\"}', '${var.attach_policy ? var.policy : \"\"}', '${var.attach_waf_log_delivery_policy ? data.aws_iam_policy_document.waf_log_delivery[0].json : \"\"}'])}" + } + } + }, + { + "aws_iam_policy_document": { + "elb_log_delivery": { + "count": "${local.create_bucket && var.attach_elb_log_delivery_policy && !var.is_directory_bucket ? 1 : 0}", + "dynamic": [ + { + "statement": { + "for_each": "${{for k , v in local.elb_service_accounts : k => v if k == data.aws_region.current.region}}", + "content": [ + { + "sid": "${format(\"ELBRegion%s\", title(statement.key))}", + "principals": [ + { + "type": "AWS", + "identifiers": [ + "${format(\"arn:%s:iam::%s:root\", data.aws_partition.current.partition, statement.value)}" + ] + } + ], + "effect": "Allow", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ] + } + ] + } + } + ], + "statement": [ + { + "sid": "", + "principals": [ + { + "type": "Service", + "identifiers": [ + "logdelivery.elasticloadbalancing.amazonaws.com" + ] + } + ], + "effect": "Allow", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "lb_log_delivery": { + "count": "${local.create_bucket && var.attach_lb_log_delivery_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "AlbNlbLogDeliveryWrite", + "principals": [ + { + "type": "Service", + "identifiers": [ + "delivery.logs.amazonaws.com" + ] + } + ], + "effect": "Allow", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "condition": [ + { + "test": "StringEquals", + "variable": "s3:x-amz-acl", + "values": [ + "bucket-owner-full-control" + ] + } + ], + "dynamic": [ + { + "condition": { + "for_each": "${length(var.lb_log_delivery_policy_source_organizations) > 0 ? [True] : []}", + "content": [ + { + "test": "StringEquals", + "variable": "aws:ResourceOrgID", + "values": "${var.lb_log_delivery_policy_source_organizations}" + } + ] + } + } + ] + }, + { + "sid": "AlbNlbLogDeliveryAclCheck", + "effect": "Allow", + "principals": [ + { + "type": "Service", + "identifiers": [ + "delivery.logs.amazonaws.com" + ] + } + ], + "actions": [ + "s3:GetBucketAcl", + "s3:ListBucket" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}" + ], + "dynamic": [ + { + "condition": { + "for_each": "${length(var.lb_log_delivery_policy_source_organizations) > 0 ? [True] : []}", + "content": [ + { + "test": "StringEquals", + "variable": "aws:ResourceOrgID", + "values": "${var.lb_log_delivery_policy_source_organizations}" + } + ] + } + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "access_log_delivery": { + "count": "${local.create_bucket && var.attach_access_log_delivery_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "AWSAccessLogDeliveryWrite", + "principals": [ + { + "type": "Service", + "identifiers": [ + "logging.s3.amazonaws.com" + ] + } + ], + "effect": "Allow", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "dynamic": [ + { + "condition": { + "for_each": "${length(var.access_log_delivery_policy_source_buckets) != 0 ? [True] : []}", + "content": [ + { + "test": "ForAnyValue:ArnLike", + "variable": "aws:SourceArn", + "values": "${var.access_log_delivery_policy_source_buckets}" + } + ] + } + }, + { + "condition": { + "for_each": "${length(var.access_log_delivery_policy_source_accounts) != 0 ? [True] : []}", + "content": [ + { + "test": "ForAnyValue:StringEquals", + "variable": "aws:SourceAccount", + "values": "${var.access_log_delivery_policy_source_accounts}" + } + ] + } + }, + { + "condition": { + "for_each": "${length(var.access_log_delivery_policy_source_organizations) > 0 ? [True] : []}", + "content": [ + { + "test": "StringEquals", + "variable": "aws:ResourceOrgID", + "values": "${var.access_log_delivery_policy_source_organizations}" + } + ] + } + } + ] + }, + { + "sid": "AWSAccessLogDeliveryAclCheck", + "effect": "Allow", + "principals": [ + { + "type": "Service", + "identifiers": [ + "logging.s3.amazonaws.com" + ] + } + ], + "actions": [ + "s3:GetBucketAcl" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}" + ], + "dynamic": [ + { + "condition": { + "for_each": "${length(var.access_log_delivery_policy_source_organizations) > 0 ? [True] : []}", + "content": [ + { + "test": "StringEquals", + "variable": "aws:ResourceOrgID", + "values": "${var.access_log_delivery_policy_source_organizations}" + } + ] + } + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "waf_log_delivery": { + "count": "${local.create_bucket && var.attach_waf_log_delivery_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "WafLogDeliveryWrite", + "effect": "Allow", + "principals": [ + { + "type": "Service", + "identifiers": [ + "delivery.logs.amazonaws.com" + ] + } + ], + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/AWSLogs/${data.aws_caller_identity.current.id}/*" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + }, + { + "test": "StringEquals", + "values": [ + "${data.aws_caller_identity.current.id}" + ], + "variable": "aws:SourceAccount" + }, + { + "test": "ArnLike", + "values": [ + "arn:${data.aws_partition.current.partition}:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.id}:*" + ], + "variable": "aws:SourceArn" + } + ] + }, + { + "sid": "WafLogDeliveryAclCheck", + "effect": "Allow", + "principals": [ + { + "type": "Service", + "identifiers": [ + "delivery.logs.amazonaws.com" + ] + } + ], + "actions": [ + "s3:GetBucketAcl" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "${data.aws_caller_identity.current.id}" + ], + "variable": "aws:SourceAccount" + }, + { + "test": "ArnLike", + "values": [ + "arn:${data.aws_partition.current.partition}:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.id}:*" + ], + "variable": "aws:SourceArn" + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "cloudtrail_log_delivery": { + "count": "${local.create_bucket && var.attach_cloudtrail_log_delivery_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "AWSCloudTrailAclCheck", + "principals": [ + { + "type": "Service", + "identifiers": [ + "cloudtrail.amazonaws.com" + ] + } + ], + "actions": [ + "s3:GetBucketAcl" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}" + ] + }, + { + "sid": "AWSCloudTrailWrite", + "principals": [ + { + "type": "Service", + "identifiers": [ + "cloudtrail.amazonaws.com" + ] + } + ], + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/AWSLogs/*" + ], + "condition": [ + { + "test": "StringEquals", + "variable": "s3:x-amz-acl", + "values": [ + "bucket-owner-full-control" + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "deny_insecure_transport": { + "count": "${local.create_bucket && var.attach_deny_insecure_transport_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denyInsecureTransport", + "effect": "Deny", + "actions": [ + "s3:*" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}", + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "type": "*", + "identifiers": [ + "*" + ] + } + ], + "condition": [ + { + "test": "Bool", + "variable": "aws:SecureTransport", + "values": [ + "false" + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "require_latest_tls": { + "count": "${local.create_bucket && var.attach_require_latest_tls_policy && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denyOutdatedTLS", + "effect": "Deny", + "actions": [ + "s3:*" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}", + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "type": "*", + "identifiers": [ + "*" + ] + } + ], + "condition": [ + { + "test": "NumericLessThan", + "variable": "s3:TlsVersion", + "values": [ + "1.2" + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "deny_incorrect_encryption_headers": { + "count": "${local.create_bucket && var.attach_deny_incorrect_encryption_headers && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denyIncorrectEncryptionHeaders", + "effect": "Deny", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "identifiers": [ + "*" + ], + "type": "*" + } + ], + "condition": [ + { + "test": "StringNotEquals", + "variable": "s3:x-amz-server-side-encryption", + "values": "${try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm, None) == \"aws:kms\" ? ['aws:kms'] : ['AES256']}" + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "deny_incorrect_kms_key_sse": { + "count": "${local.create_bucket && var.attach_deny_incorrect_kms_key_sse && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denyIncorrectKmsKeySse", + "effect": "Deny", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "identifiers": [ + "*" + ], + "type": "*" + } + ], + "condition": [ + { + "test": "StringNotEquals", + "variable": "s3:x-amz-server-side-encryption-aws-kms-key-id", + "values": [ + "${try(var.allowed_kms_key_arn, None)}" + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "deny_unencrypted_object_uploads": { + "count": "${local.create_bucket && var.attach_deny_unencrypted_object_uploads && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denyUnencryptedObjectUploads", + "effect": "Deny", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "identifiers": [ + "*" + ], + "type": "*" + } + ], + "condition": [ + { + "test": "Null", + "variable": "s3:x-amz-server-side-encryption", + "values": [ + true + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "deny_ssec_encrypted_object_uploads": { + "count": "${local.create_bucket && var.attach_deny_ssec_encrypted_object_uploads && !var.is_directory_bucket ? 1 : 0}", + "statement": [ + { + "sid": "denySSECEncryptedObjectUploads", + "effect": "Deny", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "identifiers": [ + "*" + ], + "type": "*" + } + ], + "condition": [ + { + "test": "Null", + "variable": "s3:x-amz-server-side-encryption-customer-algorithm", + "values": [ + false + ] + } + ] + } + ] + } + } + }, + { + "aws_iam_policy_document": { + "inventory_and_analytics_destination_policy": { + "count": "${local.create_bucket && !var.is_directory_bucket && var.attach_inventory_destination_policy || var.attach_analytics_destination_policy ? 1 : 0}", + "statement": [ + { + "sid": "destinationInventoryAndAnalyticsPolicy", + "effect": "Allow", + "actions": [ + "s3:PutObject" + ], + "resources": [ + "${aws_s3_bucket.this[0].arn}/*" + ], + "principals": [ + { + "type": "Service", + "identifiers": [ + "s3.amazonaws.com" + ] + } + ], + "condition": [ + { + "test": "ArnLike", + "variable": "aws:SourceArn", + "values": "${compact(distinct(['${var.inventory_self_source_destination ? aws_s3_bucket.this[0].arn : var.inventory_source_bucket_arn}', '${var.analytics_self_source_destination ? aws_s3_bucket.this[0].arn : var.analytics_source_bucket_arn}']))}" + }, + { + "test": "StringEquals", + "values": "${compact(distinct(['${var.inventory_self_source_destination ? data.aws_caller_identity.current.id : var.inventory_source_account_id}', '${var.analytics_self_source_destination ? data.aws_caller_identity.current.id : var.analytics_source_account_id}']))}", + "variable": "aws:SourceAccount" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ] + } + ] + } + } + } + ], + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/main.tf": [ + { + "aws_cloudfront_cache_policy": { + "this": { + "for_each": "${toset([for v in local.cache_behaviors : v.cache_policy_name if v.cache_policy_name != None])}", + "name": "${each.key}" + } + } + }, + { + "aws_cloudfront_origin_request_policy": { + "this": { + "for_each": "${toset([for v in local.cache_behaviors : v.origin_request_policy_name if v.origin_request_policy_name != None])}", + "name": "${each.key}" + } + } + }, + { + "aws_cloudfront_response_headers_policy": { + "this": { + "for_each": "${toset([for v in local.cache_behaviors : v.response_headers_policy_name if v.response_headers_policy_name != None])}", + "name": "${each.key}" + } + } + } + ] + }, + "varfile_list": [ + "/Users/patrick/git/terravision/tests/fixtures/aws_terraform/static-website/variables.tf", + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_s3-bucket_aws;s3_bucket;/variables.tf", + "/Users/patrick/.terravision/module_cache/terraform-aws-modules_cloudfront_aws;cloudfront;/variables.tf" + ], + "tempdir": "" +} \ No newline at end of file From 77b524ea629e9de78dc26924ea31f120276e5e76 Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 09:43:23 +0000 Subject: [PATCH 7/8] actions --- .github/workflows/lint-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index a81c499..b94034f 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -54,7 +54,7 @@ jobs: # Retrieve temporary AWS credentials #---------------------------------------------- - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v3 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::166659698090:role/githubactions role-session-name: ghasession From c88250a63291b7bca390a5c9eaa808d96ea36a41 Mon Sep 17 00:00:00 2001 From: patrickchugh Date: Thu, 25 Dec 2025 09:43:50 +0000 Subject: [PATCH 8/8] black --- modules/tfwrapper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/tfwrapper.py b/modules/tfwrapper.py index ad3fc5c..0305c44 100644 --- a/modules/tfwrapper.py +++ b/modules/tfwrapper.py @@ -332,7 +332,9 @@ def setup_tfdata(tfdata: Dict[str, Any]) -> Dict[str, Any]: details.update(object["change"]["after_sensitive"]) # Add module name if resource is in a module if "module." in object["address"]: - modname = object["module_address"].split("module.")[-1].split(".")[0] + modname = ( + object["module_address"].split("module.")[-1].split(".")[0] + ) details["module"] = modname else: details["module"] = "main"