From b73470dabdfdd48ed5d47aac074fc1e1887731ac Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Mon, 2 Dec 2024 17:32:19 -0700 Subject: [PATCH] bugfix: fix flow logs and tgw attachment (#94) * bugfix: fix flow logs and tgw attachment BREAKING CHANGE: flow logs and tgw attachment were not working properly - Fixed tgw attachments from creating multiple attachments - Updated the `flow_logs` module to create multiple flow logs based on the inputs as lists - Updated the `flow_logs` module ID variables to be plural * corrected pluralization * updated pluralize of all flow_log ids * correcting list of resources in the modules * okay now to just a normal list * getting all of the ids from the for_each resource * another attempt * going back to values * corrected conditional logic * corrects the for_each calculated value * corrected index * converted for_each to count in flow_logs * back to the normal var.vpc_ids * changed output key and added new outputs * fixing the name of flow_logs * chore: terraform fmt and terraform-docs --------- Co-authored-by: zachreborn --- modules/aws/flow_logs/README.md | 52 +++++++++++-------- modules/aws/flow_logs/main.tf | 31 +++++++---- modules/aws/flow_logs/variables.tf | 30 +++++------ .../aws/transit_gateway/attachment/README.md | 1 + .../aws/transit_gateway/attachment/main.tf | 30 +++++------ .../aws/transit_gateway/attachment/outputs.tf | 24 ++++++++- modules/aws/transit_gateway/tgw/main.tf | 2 +- modules/aws/vpc/main.tf | 2 +- 8 files changed, 107 insertions(+), 65 deletions(-) diff --git a/modules/aws/flow_logs/README.md b/modules/aws/flow_logs/README.md index e0290c28..e03cc09e 100644 --- a/modules/aws/flow_logs/README.md +++ b/modules/aws/flow_logs/README.md @@ -1,7 +1,7 @@ - + + [![Contributors][contributors-shield]][contributors-url] [![Forks][forks-shield]][forks-url] [![Stargazers][stars-shield]][stars-url] @@ -18,7 +19,6 @@ [![MIT License][license-shield]][license-url] [![LinkedIn][linkedin-shield]][linkedin-url] -
@@ -28,7 +28,7 @@

Flow Logs Module

- This module sets up each componenet required to capture Flow Logs with the parameters specified. By default this module will be set up to work without any changes to variables other than the flow log capture source. The result of this module creates a unique cloudwatch log group with a prefix of 'flow_logs', an IAM policy and IAM role which can be used with ENI flow logs to deliver logs to that cloudwatch log group. One of flow_eni_id, flow_subnet_id, flow_transit_gateway_id, flow_transit_gateway_attachment_id, or flow_vpc_id must be provided. + This module sets up each componenet required to capture Flow Logs with the parameters specified. By default this module will be set up to work without any changes to variables other than the flow log capture source. The result of this module creates a unique cloudwatch log group with a prefix of 'flow_logs', an IAM policy and IAM role which can be used with ENI flow logs to deliver logs to that cloudwatch log group. One of flow_eni_ids, flow_subnet_ids, flow_transit_gateway_ids, flow_transit_gateway_attachment_ids, or flow_vpc_ids must be provided.
Explore the docs ยป
@@ -41,7 +41,6 @@

-
Table of Contents @@ -59,22 +58,26 @@
- + ## Usage ### Simple Example + This simple example creates a flow log for a VPC. The flow logs are delivered to a CloudWatch Logs log group. + ``` module "flow_logs" { source = "github.com/zachreborn/terraform-modules//modules/aws/flow_logs" - flow_vpc_id = module.vpc.id + flow_vpc_ids = module.vpc.id } ``` ### VPC Example + This example configures Flow Logs to capture all traffic in a VPC. The flow logs are delivered to a CloudWatch Logs log group. + ``` module "vpc_flow_logs" { source = "github.com/zachreborn/terraform-modules//modules/aws/flow_logs" @@ -91,13 +94,15 @@ module "vpc_flow_logs" { flow_log_format = var.flow_log_format flow_max_aggregation_interval = var.flow_max_aggregation_interval flow_traffic_type = var.flow_traffic_type - flow_vpc_id = aws_vpc.vpc.id + flow_vpc_ids = aws_vpc.vpc.id tags = var.tags } ``` ### Transit Gateway Example + This example configures Flow Logs to capture all traffic in a Transit Gateway. The flow logs are delivered to a CloudWatch Logs log group. + ``` module "vpc_flow_logs" { source = "github.com/zachreborn/terraform-modules//modules/aws/flow_logs" @@ -114,14 +119,16 @@ module "vpc_flow_logs" { flow_log_format = var.flow_log_format flow_max_aggregation_interval = var.flow_max_aggregation_interval flow_traffic_type = var.flow_traffic_type - flow_transit_gateway_id = aws_ec2_transit_gateway.transit_gateway.id + flow_transit_gateway_ids = aws_ec2_transit_gateway.transit_gateway.id tags = var.tags } ``` ### Transit Gateway Attachment Example + This example configures Flow Logs to capture all traffic in a Transit Gateway Attachment. The flow logs are delivered to a CloudWatch Logs log group. + ``` module "vpc_flow_logs" { source = "github.com/zachreborn/terraform-modules//modules/aws/flow_logs" @@ -138,7 +145,7 @@ module "vpc_flow_logs" { flow_log_format = var.flow_log_format flow_max_aggregation_interval = var.flow_max_aggregation_interval flow_traffic_type = var.flow_traffic_type - flow_transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this.id + flow_transit_gateway_attachment_ids = aws_ec2_transit_gateway_vpc_attachment.this.id tags = var.tags } ``` @@ -172,7 +179,7 @@ No modules. | Name | Type | |------|------| | [aws_cloudwatch_log_group.log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_flow_log.vpc_flow](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | +| [aws_flow_log.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | | [aws_iam_policy.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.role_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -188,15 +195,15 @@ No modules. | [cloudwatch\_name\_prefix](#input\_cloudwatch\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. | `string` | `"flow_logs_"` | no | | [cloudwatch\_retention\_in\_days](#input\_cloudwatch\_retention\_in\_days) | (Optional) Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire. | `number` | `90` | no | | [flow\_deliver\_cross\_account\_role](#input\_flow\_deliver\_cross\_account\_role) | (Optional) The ARN of the IAM role that posts logs to CloudWatch Logs in a different account. | `string` | `null` | no | -| [flow\_eni\_id](#input\_flow\_eni\_id) | (Optional) Elastic Network Interface ID to attach the flow logs to. | `string` | `null` | no | +| [flow\_eni\_ids](#input\_flow\_eni\_ids) | (Optional) List of Elastic Network Interface IDs to attach the flow logs to. | `list(string)` | `null` | no | | [flow\_log\_destination\_type](#input\_flow\_log\_destination\_type) | (Optional) The type of the logging destination. Valid values: cloud-watch-logs, s3. Default: cloud-watch-logs. | `string` | `"cloud-watch-logs"` | no | | [flow\_log\_format](#input\_flow\_log\_format) | (Optional) The fields to include in the flow log record, in the order in which they should appear. For more information, see Flow Log Records. Default: fields are in the order that they are described in the Flow Log Records section. | `string` | `null` | no | | [flow\_max\_aggregation\_interval](#input\_flow\_max\_aggregation\_interval) | (Optional) The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: 60 seconds (1 minute) or 600 seconds (10 minutes). Default: 600. | `number` | `60` | no | -| [flow\_subnet\_id](#input\_flow\_subnet\_id) | (Optional) Subnet ID to attach the flow logs to. | `string` | `null` | no | +| [flow\_subnet\_ids](#input\_flow\_subnet\_ids) | (Optional) List of Subnet IDs to attach the flow logs to. | `list(string)` | `null` | no | | [flow\_traffic\_type](#input\_flow\_traffic\_type) | (Optional) The type of traffic to capture. Valid values: ACCEPT,REJECT, ALL. | `string` | `"ALL"` | no | -| [flow\_transit\_gateway\_attachment\_id](#input\_flow\_transit\_gateway\_attachment\_id) | (Optional) The ID of the transit gateway attachment to attach the flow logs to. | `string` | `null` | no | -| [flow\_transit\_gateway\_id](#input\_flow\_transit\_gateway\_id) | (Optional) The ID of the transit gateway to attach the flow logs to. | `string` | `null` | no | -| [flow\_vpc\_id](#input\_flow\_vpc\_id) | (Optional) VPC ID to attach to. | `string` | `null` | no | +| [flow\_transit\_gateway\_attachment\_ids](#input\_flow\_transit\_gateway\_attachment\_ids) | (Optional) List of IDs of the transit gateway attachments to attach the flow logs to. | `list(string)` | `null` | no | +| [flow\_transit\_gateway\_ids](#input\_flow\_transit\_gateway\_ids) | (Optional) List of IDs of the transit gateways to attach the flow logs to. | `list(string)` | `null` | no | +| [flow\_vpc\_ids](#input\_flow\_vpc\_ids) | (Optional) List of VPC IDs to attach the flow logs to. | `list(string)` | `null` | no | | [iam\_policy\_description](#input\_iam\_policy\_description) | (Optional, Forces new resource) Description of the IAM policy. | `string` | `"Used with flow logs to send packet capture logs to a CloudWatch log group."` | no | | [iam\_policy\_name\_prefix](#input\_iam\_policy\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with name. | `string` | `"flow_log_policy_"` | no | | [iam\_policy\_path](#input\_iam\_policy\_path) | (Optional, default '/') Path in which to create the policy. See IAM Identifiers for more information. | `string` | `"/"` | no | @@ -223,15 +230,15 @@ No modules. + ## License Distributed under the MIT License. See `LICENSE.txt` for more information.

(back to top)

- - + ## Contact Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co @@ -240,19 +247,18 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c

(back to top)

- - + ## Acknowledgments -* [Zachary Hill](https://zacharyhill.co) -* [Jake Jones](https://github.com/jakeasarus) +- [Zachary Hill](https://zacharyhill.co) +- [Jake Jones](https://github.com/jakeasarus)

(back to top)

- + [contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge [contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors [forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge @@ -267,4 +273,4 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c [linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ [product-screenshot]: /images/screenshot.webp [Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform -[Terraform-url]: https://terraform.io \ No newline at end of file +[Terraform-url]: https://terraform.io diff --git a/modules/aws/flow_logs/main.tf b/modules/aws/flow_logs/main.tf index a8d993b4..72b10343 100644 --- a/modules/aws/flow_logs/main.tf +++ b/modules/aws/flow_logs/main.tf @@ -14,6 +14,20 @@ terraform { data "aws_caller_identity" "current" {} data "aws_region" "current" {} +########################### +# Locals +########################### +locals { + + flow_logs_source = coalesce( + var.flow_eni_ids, + var.flow_subnet_ids, + var.flow_transit_gateway_ids, + var.flow_transit_gateway_attachment_ids, + var.flow_vpc_ids + ) +} + ########################### # KMS Encryption Key ########################### @@ -122,23 +136,22 @@ resource "aws_iam_role_policy_attachment" "role_attach" { policy_arn = aws_iam_policy.policy.arn } - ########################### # Flow Log ########################### - -resource "aws_flow_log" "vpc_flow" { +resource "aws_flow_log" "this" { + count = length(local.flow_logs_source) deliver_cross_account_role = var.flow_deliver_cross_account_role - eni_id = var.flow_eni_id + eni_id = var.flow_eni_ids != null ? local.flow_logs_source[count.index] : null iam_role_arn = aws_iam_role.role.arn log_destination_type = var.flow_log_destination_type log_destination = aws_cloudwatch_log_group.log_group.arn log_format = var.flow_log_format max_aggregation_interval = var.flow_max_aggregation_interval - subnet_id = var.flow_subnet_id + subnet_id = var.flow_subnet_ids != null ? local.flow_logs_source[count.index] : null tags = var.tags - transit_gateway_id = var.flow_transit_gateway_id - transit_gateway_attachment_id = var.flow_transit_gateway_attachment_id + transit_gateway_id = var.flow_transit_gateway_ids != null ? local.flow_logs_source[count.index] : null + transit_gateway_attachment_id = var.flow_transit_gateway_attachment_ids != null ? local.flow_logs_source[count.index] : null traffic_type = var.flow_traffic_type - vpc_id = var.flow_vpc_id -} \ No newline at end of file + vpc_id = var.flow_vpc_ids != null ? local.flow_logs_source[count.index] : null +} diff --git a/modules/aws/flow_logs/variables.tf b/modules/aws/flow_logs/variables.tf index 9119b0c7..50e79b87 100644 --- a/modules/aws/flow_logs/variables.tf +++ b/modules/aws/flow_logs/variables.tf @@ -144,9 +144,9 @@ variable "flow_deliver_cross_account_role" { default = null } -variable "flow_eni_id" { - type = string - description = "(Optional) Elastic Network Interface ID to attach the flow logs to." +variable "flow_eni_ids" { + type = list(string) + description = "(Optional) List of Elastic Network Interface IDs to attach the flow logs to." default = null } @@ -168,9 +168,9 @@ variable "flow_max_aggregation_interval" { default = 60 } -variable "flow_subnet_id" { - type = string - description = "(Optional) Subnet ID to attach the flow logs to." +variable "flow_subnet_ids" { + type = list(string) + description = "(Optional) List of Subnet IDs to attach the flow logs to." default = null } @@ -180,21 +180,21 @@ variable "flow_traffic_type" { default = "ALL" } -variable "flow_transit_gateway_id" { - type = string - description = "(Optional) The ID of the transit gateway to attach the flow logs to." +variable "flow_transit_gateway_ids" { + type = list(string) + description = "(Optional) List of IDs of the transit gateways to attach the flow logs to." default = null } -variable "flow_transit_gateway_attachment_id" { - type = string - description = "(Optional) The ID of the transit gateway attachment to attach the flow logs to." +variable "flow_transit_gateway_attachment_ids" { + type = list(string) + description = "(Optional) List of IDs of the transit gateway attachments to attach the flow logs to." default = null } -variable "flow_vpc_id" { - type = string - description = "(Optional) VPC ID to attach to." +variable "flow_vpc_ids" { + type = list(string) + description = "(Optional) List of VPC IDs to attach the flow logs to." default = null } diff --git a/modules/aws/transit_gateway/attachment/README.md b/modules/aws/transit_gateway/attachment/README.md index 07b35d25..4eff93ac 100644 --- a/modules/aws/transit_gateway/attachment/README.md +++ b/modules/aws/transit_gateway/attachment/README.md @@ -141,6 +141,7 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr |------|-------------| | [ids](#output\_ids) | Map of VPC IDs and their transit gateway attachment IDs. | | [ids\_list](#output\_ids\_list) | List of transit gateway attachment IDs | +| [info](#output\_info) | A map with information about the transit gateway attachment. | | [vpc\_owner\_id](#output\_vpc\_owner\_id) | Map of VPC IDs and their owner IDs | diff --git a/modules/aws/transit_gateway/attachment/main.tf b/modules/aws/transit_gateway/attachment/main.tf index fb67c8c1..9984e910 100644 --- a/modules/aws/transit_gateway/attachment/main.tf +++ b/modules/aws/transit_gateway/attachment/main.tf @@ -30,19 +30,19 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { module "vpc_flow_logs" { source = "../../flow_logs" - for_each = var.enable_flow_logs ? var.vpc_ids : {} - cloudwatch_name_prefix = var.cloudwatch_name_prefix - cloudwatch_retention_in_days = var.cloudwatch_retention_in_days - iam_policy_name_prefix = var.iam_policy_name_prefix - iam_policy_path = var.iam_policy_path - iam_role_description = var.iam_role_description - iam_role_name_prefix = var.iam_role_name_prefix - key_name_prefix = var.key_name_prefix - flow_deliver_cross_account_role = var.flow_deliver_cross_account_role - flow_log_destination_type = var.flow_log_destination_type - flow_log_format = var.flow_log_format - flow_max_aggregation_interval = var.flow_max_aggregation_interval - flow_traffic_type = var.flow_traffic_type - flow_transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[each.key].id - tags = var.tags + count = var.enable_flow_logs ? 1 : 0 + cloudwatch_name_prefix = var.cloudwatch_name_prefix + cloudwatch_retention_in_days = var.cloudwatch_retention_in_days + iam_policy_name_prefix = var.iam_policy_name_prefix + iam_policy_path = var.iam_policy_path + iam_role_description = var.iam_role_description + iam_role_name_prefix = var.iam_role_name_prefix + key_name_prefix = var.key_name_prefix + flow_deliver_cross_account_role = var.flow_deliver_cross_account_role + flow_log_destination_type = var.flow_log_destination_type + flow_log_format = var.flow_log_format + flow_max_aggregation_interval = var.flow_max_aggregation_interval + flow_traffic_type = var.flow_traffic_type + flow_transit_gateway_attachment_ids = [for attachment, value in aws_ec2_transit_gateway_vpc_attachment.this : value.id] + tags = var.tags } diff --git a/modules/aws/transit_gateway/attachment/outputs.tf b/modules/aws/transit_gateway/attachment/outputs.tf index 300f5b01..cb957b5c 100644 --- a/modules/aws/transit_gateway/attachment/outputs.tf +++ b/modules/aws/transit_gateway/attachment/outputs.tf @@ -1,13 +1,35 @@ output "ids" { description = "Map of VPC IDs and their transit gateway attachment IDs." - value = { for attachment, value in aws_ec2_transit_gateway_vpc_attachment.this : value.vpc_id => value.id } + value = tomap({ + for attachment, value in aws_ec2_transit_gateway_vpc_attachment.this : attachment => value.id + }) } +# { +# vpc-12345678 = "tgw-attach-12345678" +# } + output "ids_list" { description = "List of transit gateway attachment IDs" value = values(aws_ec2_transit_gateway_vpc_attachment.this)[*].id } +output "info" { + description = "A map with information about the transit gateway attachment." + value = { + for attachment, values in aws_ec2_transit_gateway_vpc_attachment.this : attachment => { + appliance_mode_support = values.appliance_mode_support + dns_support = values.dns_support + ipv6_support = values.ipv6_support + security_group_referencing_support = values.security_group_referencing_support + id = values.id + subnet_ids = values.subnet_ids + transit_gateway_id = values.transit_gateway_id + vpc_owner_id = values.vpc_owner_id + } + } +} + output "vpc_owner_id" { description = "Map of VPC IDs and their owner IDs" value = { for attachment, value in aws_ec2_transit_gateway_vpc_attachment.this : value.vpc_id => value.vpc_owner_id } diff --git a/modules/aws/transit_gateway/tgw/main.tf b/modules/aws/transit_gateway/tgw/main.tf index 0073bcdd..89bf58a8 100644 --- a/modules/aws/transit_gateway/tgw/main.tf +++ b/modules/aws/transit_gateway/tgw/main.tf @@ -44,6 +44,6 @@ module "vpc_flow_logs" { flow_log_format = var.flow_log_format flow_max_aggregation_interval = var.flow_max_aggregation_interval flow_traffic_type = var.flow_traffic_type - flow_transit_gateway_id = aws_ec2_transit_gateway.transit_gateway.id + flow_transit_gateway_ids = [aws_ec2_transit_gateway.transit_gateway.id] tags = var.tags } diff --git a/modules/aws/vpc/main.tf b/modules/aws/vpc/main.tf index edf45c99..f4f29e5e 100644 --- a/modules/aws/vpc/main.tf +++ b/modules/aws/vpc/main.tf @@ -400,6 +400,6 @@ module "vpc_flow_logs" { flow_log_format = var.flow_log_format flow_max_aggregation_interval = var.flow_max_aggregation_interval flow_traffic_type = var.flow_traffic_type - flow_vpc_id = aws_vpc.vpc.id + flow_vpc_ids = [aws_vpc.vpc.id] tags = var.tags }