diff --git a/README.md b/README.md index 53900ce..6cd129e 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,154 @@ module "vpc" { } ``` +## Usage with Flow Logs + +Transit Gateway Flow Logs can be enabled to capture information about the IP traffic going to and from network interfaces in your Transit Gateway. Flow logs can help with monitoring network traffic, troubleshooting connectivity issues, and detecting anomalous traffic patterns. + +### Basic Flow Logs to CloudWatch + +```hcl +module "tgw" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "~> 2.0" + + name = "my-tgw" + description = "My TGW with flow logs enabled" + + # Enable flow logs + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tags = { + Purpose = "tgw-with-flow-logs" + } +} +``` + +### Flow Logs with Custom CloudWatch Configuration + +```hcl +module "tgw" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "~> 2.0" + + name = "my-tgw" + description = "My TGW with custom flow logs" + + # Flow log configuration + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + # CloudWatch log group settings + flow_log_cloudwatch_log_group_name_prefix = "/aws/transit-gateway/flowlogs/" + flow_log_cloudwatch_log_group_retention_in_days = 14 + flow_log_cloudwatch_log_group_kms_key_id = aws_kms_key.log_key.arn + + # Flow log settings + flow_log_traffic_type = "ALL" + flow_log_max_aggregation_interval = 60 + flow_log_log_format = "$${version} $${account-id} $${transit-gateway-id} $${transit-gateway-attachment-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${windowstart} $${windowend} $${action}" + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tgw_flow_log_tags = { + LogType = "TransitGatewayFlow" + } + + tags = { + Purpose = "tgw-with-custom-flow-logs" + } +} +``` + +### Flow Logs to S3 + +```hcl +module "tgw" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "~> 2.0" + + name = "my-tgw" + description = "My TGW with S3 flow logs" + + # Flow log configuration for S3 + enable_flow_log = true + flow_log_destination_type = "s3" + flow_log_destination_arn = aws_s3_bucket.flow_logs.arn + + # S3 destination options + flow_log_file_format = "parquet" + flow_log_hive_compatible_partitions = true + flow_log_per_hour_partition = true + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tags = { + Purpose = "tgw-with-s3-flow-logs" + } +} + +resource "aws_s3_bucket" "flow_logs" { + bucket = "my-tgw-flow-logs-bucket" + force_destroy = true +} + +resource "aws_s3_bucket_policy" "flow_logs" { + bucket = aws_s3_bucket.flow_logs.id + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AWSLogDeliveryWrite" + Effect = "Allow" + Principal = { + Service = "delivery.logs.amazonaws.com" + } + Action = "s3:PutObject" + Resource = "${aws_s3_bucket.flow_logs.arn}/*" + Condition = { + StringEquals = { + "s3:x-amz-acl" = "bucket-owner-full-control" + } + } + }, + { + Sid = "AWSLogDeliveryAclCheck" + Effect = "Allow" + Principal = { + Service = "delivery.logs.amazonaws.com" + } + Action = "s3:GetBucketAcl" + Resource = aws_s3_bucket.flow_logs.arn + } + ] + }) +} +``` + ## Examples -- [Complete example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete) shows TGW in combination with the [VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc) and [Resource Access Manager (RAM)](https://aws.amazon.com/ram/). +- [Complete example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete) shows TGW in combination with the [VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc), [Resource Access Manager (RAM)](https://aws.amazon.com/ram/), and basic flow logging configuration. +- [Flow Logs example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/flow-logs) demonstrates comprehensive flow logging configurations including CloudWatch Logs, S3 destinations, and external resource usage. - [Multi-account example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/multi-account) shows TGW resources shared with different AWS accounts (via [Resource Access Manager (RAM)](https://aws.amazon.com/ram/)). @@ -85,6 +230,7 @@ No modules. | Name | Type | |------|------| +| [aws_cloudwatch_log_group.flow_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_ec2_tag.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource | | [aws_ec2_transit_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway) | resource | | [aws_ec2_transit_gateway_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | @@ -92,17 +238,28 @@ No modules. | [aws_ec2_transit_gateway_route_table_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | | [aws_ec2_transit_gateway_route_table_propagation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_propagation) | resource | | [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | +| [aws_flow_log.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | +| [aws_iam_policy.tgw_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.tgw_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.tgw_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_ram_principal_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | | [aws_ram_resource_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | | [aws_ram_resource_share.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | | [aws_ram_resource_share_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share_accepter) | resource | | [aws_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.flow_log_cloudwatch_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.tgw_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN. | `string` | `null` | no | +| [create\_flow\_log\_cloudwatch\_iam\_role](#input\_create\_flow\_log\_cloudwatch\_iam\_role) | Whether to create IAM role for TGW Flow Logs | `bool` | `false` | no | +| [create\_flow\_log\_cloudwatch\_log\_group](#input\_create\_flow\_log\_cloudwatch\_log\_group) | Whether to create CloudWatch log group for TGW Flow Logs | `bool` | `false` | no | | [create\_tgw](#input\_create\_tgw) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | | [create\_tgw\_routes](#input\_create\_tgw\_routes) | Controls if TGW Route Table / Routes should be created | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | @@ -110,9 +267,27 @@ No modules. | [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `true` | no | | [enable\_default\_route\_table\_propagation](#input\_enable\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `true` | no | | [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | +| [enable\_flow\_log](#input\_enable\_flow\_log) | Whether or not to enable TGW Flow Logs | `bool` | `false` | no | | [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | | [enable\_sg\_referencing\_support](#input\_enable\_sg\_referencing\_support) | Indicates whether to enable security group referencing support | `bool` | `true` | no | | [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | +| [flow\_log\_cloudwatch\_iam\_role\_arn](#input\_flow\_log\_cloudwatch\_iam\_role\_arn) | The ARN for the IAM role that's used to post flow logs to a CloudWatch Logs log group. When flow\_log\_destination\_arn is set to ARN of Cloudwatch Logs, this argument needs to be provided | `string` | `""` | no | +| [flow\_log\_cloudwatch\_iam\_role\_conditions](#input\_flow\_log\_cloudwatch\_iam\_role\_conditions) | Additional conditions of the CloudWatch role assumption policy |
list(object({| `[]` | no | +| [flow\_log\_cloudwatch\_log\_group\_class](#input\_flow\_log\_cloudwatch\_log\_group\_class) | Specified the log class of the log group. Possible values are: STANDARD or INFREQUENT\_ACCESS | `string` | `null` | no | +| [flow\_log\_cloudwatch\_log\_group\_kms\_key\_id](#input\_flow\_log\_cloudwatch\_log\_group\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data for TGW flow logs | `string` | `null` | no | +| [flow\_log\_cloudwatch\_log\_group\_name\_prefix](#input\_flow\_log\_cloudwatch\_log\_group\_name\_prefix) | Specifies the name prefix of CloudWatch Log Group for TGW flow logs | `string` | `"/aws/tgw-flow-log/"` | no | +| [flow\_log\_cloudwatch\_log\_group\_name\_suffix](#input\_flow\_log\_cloudwatch\_log\_group\_name\_suffix) | Specifies the name suffix of CloudWatch Log Group for TGW flow logs | `string` | `""` | no | +| [flow\_log\_cloudwatch\_log\_group\_retention\_in\_days](#input\_flow\_log\_cloudwatch\_log\_group\_retention\_in\_days) | Specifies the number of days you want to retain log events in the specified log group for TGW flow logs | `number` | `null` | no | +| [flow\_log\_cloudwatch\_log\_group\_skip\_destroy](#input\_flow\_log\_cloudwatch\_log\_group\_skip\_destroy) | Set to true if you do not wish the log group (and any logs it may contain) to be deleted at destroy time, and instead just remove the log group from the Terraform state | `bool` | `false` | no | +| [flow\_log\_deliver\_cross\_account\_role](#input\_flow\_log\_deliver\_cross\_account\_role) | (Optional) ARN of the IAM role that allows Amazon EC2 to publish flow logs across accounts. | `string` | `null` | no | +| [flow\_log\_destination\_arn](#input\_flow\_log\_destination\_arn) | The ARN of the CloudWatch log group or S3 bucket where TGW Flow Logs will be pushed. If this ARN is a S3 bucket the appropriate permissions need to be set on that bucket's policy. When create\_flow\_log\_cloudwatch\_log\_group is set to false this argument must be provided | `string` | `""` | no | +| [flow\_log\_destination\_type](#input\_flow\_log\_destination\_type) | Type of flow log destination. Can be s3, kinesis-data-firehose or cloud-watch-logs | `string` | `"cloud-watch-logs"` | no | +| [flow\_log\_file\_format](#input\_flow\_log\_file\_format) | (Optional) The format for the flow log. Valid values: `plain-text`, `parquet` | `string` | `null` | no | +| [flow\_log\_hive\_compatible\_partitions](#input\_flow\_log\_hive\_compatible\_partitions) | (Optional) Indicates whether to use Hive-compatible prefixes for flow logs stored in Amazon S3 | `bool` | `false` | no | +| [flow\_log\_log\_format](#input\_flow\_log\_log\_format) | The fields to include in the flow log record, in the order in which they should appear | `string` | `null` | no | +| [flow\_log\_max\_aggregation\_interval](#input\_flow\_log\_max\_aggregation\_interval) | The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: `60` seconds | `number` | `60` | no | +| [flow\_log\_per\_hour\_partition](#input\_flow\_log\_per\_hour\_partition) | (Optional) Indicates whether to partition the flow log per hour. This reduces the cost and response time for queries | `bool` | `false` | no | +| [flow\_log\_traffic\_type](#input\_flow\_log\_traffic\_type) | The type of traffic to capture. Valid values: ACCEPT, REJECT, ALL | `string` | `"ALL"` | no | | [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | | [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share. | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | @@ -122,6 +297,12 @@ No modules. | [share\_tgw](#input\_share\_tgw) | Whether to share your transit gateway with other accounts | `bool` | `true` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [tgw\_default\_route\_table\_tags](#input\_tgw\_default\_route\_table\_tags) | Additional tags for the Default TGW route table | `map(string)` | `{}` | no | +| [tgw\_flow\_log\_iam\_policy\_name](#input\_tgw\_flow\_log\_iam\_policy\_name) | Name of the IAM policy | `string` | `"tgw-flow-log-to-cloudwatch"` | no | +| [tgw\_flow\_log\_iam\_policy\_use\_name\_prefix](#input\_tgw\_flow\_log\_iam\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`tgw_flow_log_iam_policy_name`) is used as a prefix | `bool` | `true` | no | +| [tgw\_flow\_log\_iam\_role\_name](#input\_tgw\_flow\_log\_iam\_role\_name) | Name to use on the TGW Flow Log IAM role created | `string` | `"tgw-flow-log-role"` | no | +| [tgw\_flow\_log\_iam\_role\_use\_name\_prefix](#input\_tgw\_flow\_log\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`tgw_flow_log_iam_role_name`) is used as a prefix | `bool` | `true` | no | +| [tgw\_flow\_log\_permissions\_boundary](#input\_tgw\_flow\_log\_permissions\_boundary) | The ARN of the Permissions Boundary for the TGW Flow Log IAM Role | `string` | `null` | no | +| [tgw\_flow\_log\_tags](#input\_tgw\_flow\_log\_tags) | Additional tags for the TGW Flow Logs | `map(string)` | `{}` | no | | [tgw\_route\_table\_tags](#input\_tgw\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | | [tgw\_vpc\_attachment\_tags](#input\_tgw\_vpc\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | @@ -151,6 +332,11 @@ No modules. | [ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | | [ram\_principal\_association\_id](#output\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [tgw\_flow\_log\_cloudwatch\_iam\_role\_arn](#output\_tgw\_flow\_log\_cloudwatch\_iam\_role\_arn) | The ARN of the IAM role used when pushing logs to Cloudwatch log group | +| [tgw\_flow\_log\_deliver\_cross\_account\_role](#output\_tgw\_flow\_log\_deliver\_cross\_account\_role) | The ARN of the IAM role used when pushing logs cross account | +| [tgw\_flow\_log\_destination\_arn](#output\_tgw\_flow\_log\_destination\_arn) | The ARN of the destination for TGW Flow Logs | +| [tgw\_flow\_log\_destination\_type](#output\_tgw\_flow\_log\_destination\_type) | The type of the destination for TGW Flow Logs | +| [tgw\_flow\_log\_id](#output\_tgw\_flow\_log\_id) | The ID of the Flow Log resource | ## Authors diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 1f372a8..af00a99 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -35,6 +35,15 @@ module "tgw" { # When "true", allows service discovery through IGMP enable_multicast_support = false + # Flow log configuration (optional) + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + flow_log_cloudwatch_log_group_retention_in_days = 14 + flow_log_traffic_type = "ALL" + flow_log_max_aggregation_interval = 600 + vpc_attachments = { vpc1 = { vpc_id = module.vpc1.vpc_id diff --git a/examples/flow-logs/README.md b/examples/flow-logs/README.md new file mode 100644 index 0000000..797340b --- /dev/null +++ b/examples/flow-logs/README.md @@ -0,0 +1,194 @@ +# Transit Gateway Flow Logs Example + +This example demonstrates how to configure Transit Gateway Flow Logs with various destination options. + +## Features + +This example shows how to: + +- Enable Transit Gateway Flow Logs to CloudWatch Logs +- Configure custom log format and retention +- Set up S3 destination for flow logs +- Use external CloudWatch Log Group and IAM role +- Configure flow log aggregation intervals + +## Usage + +To run this example, you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources. + +## Flow Log Destinations + +### CloudWatch Logs (Default) + +Flow logs are sent to CloudWatch Logs with automatic IAM role and log group creation: + +```hcl +module "tgw_with_cloudwatch_logs" { + source = "../../" + + name = "tgw-flow-logs-cloudwatch" + description = "TGW with CloudWatch flow logs" + + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + # CloudWatch specific settings + flow_log_cloudwatch_log_group_retention_in_days = 30 + flow_log_cloudwatch_log_group_kms_key_id = aws_kms_key.log_encryption.arn + + # Traffic settings + flow_log_traffic_type = "ALL" + flow_log_max_aggregation_interval = 60 + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tags = local.tags +} +``` + +### S3 Destination + +Flow logs are sent to S3 bucket with Parquet format: + +```hcl +module "tgw_with_s3_logs" { + source = "../../" + + name = "tgw-flow-logs-s3" + description = "TGW with S3 flow logs" + + enable_flow_log = true + flow_log_destination_type = "s3" + flow_log_destination_arn = aws_s3_bucket.flow_logs.arn + + # S3 specific settings + flow_log_file_format = "parquet" + flow_log_hive_compatible_partitions = true + flow_log_per_hour_partition = true + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tags = local.tags +} +``` + +### External Resources + +Using existing CloudWatch Log Group and IAM role: + +```hcl +module "tgw_with_external_resources" { + source = "../../" + + name = "tgw-flow-logs-external" + description = "TGW with external flow log resources" + + enable_flow_log = true + create_flow_log_cloudwatch_log_group = false + create_flow_log_cloudwatch_iam_role = false + + flow_log_destination_arn = aws_cloudwatch_log_group.external.arn + flow_log_cloudwatch_iam_role_arn = aws_iam_role.external.arn + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + } + } + + tags = local.tags +} +``` + +## Custom Log Format + +You can specify a custom log format to capture specific fields: + +```hcl +# Custom log format with specific fields +flow_log_log_format = "$${version} $${account-id} $${transit-gateway-id} $${transit-gateway-attachment-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${windowstart} $${windowend} $${action}" +``` + +Available fields for Transit Gateway Flow Logs: +- `version` - VPC Flow Logs version +- `account-id` - AWS account ID +- `transit-gateway-id` - Transit Gateway ID +- `transit-gateway-attachment-id` - Transit Gateway attachment ID +- `srcaddr` - Source address +- `dstaddr` - Destination address +- `srcport` - Source port +- `dstport` - Destination port +- `protocol` - IANA protocol number +- `packets` - Number of packets transferred +- `bytes` - Number of bytes transferred +- `windowstart` - Start time of the aggregation interval +- `windowend` - End time of the aggregation interval +- `action` - Action that is associated with the traffic (ACCEPT or REJECT) + +## Security Considerations + +- Flow logs may contain sensitive network information +- Use KMS encryption for CloudWatch Logs +- Implement proper S3 bucket policies for S3 destinations +- Consider log retention policies to manage costs +- Use IAM policies to restrict access to flow log data + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13.1 | +| [aws](#requirement\_aws) | >= 4.4 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.4 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [tgw\_with\_cloudwatch\_logs](#module\_tgw\_with\_cloudwatch\_logs) | ../../ | n/a | +| [tgw\_with\_s3\_logs](#module\_tgw\_with\_s3\_logs) | ../../ | n/a | +| [tgw\_with\_external\_resources](#module\_tgw\_with\_external\_resources) | ../../ | n/a | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_kms_key.log_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_s3_bucket.flow_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_policy.flow_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | + +## Outputs + +| Name | Description | +|------|-------------| +| [tgw\_flow\_log\_cloudwatch\_id](#output\_tgw\_flow\_log\_cloudwatch\_id) | CloudWatch flow log ID | +| [tgw\_flow\_log\_s3\_id](#output\_tgw\_flow\_log\_s3\_id) | S3 flow log ID | +| [tgw\_flow\_log\_external\_id](#output\_tgw\_flow\_log\_external\_id) | External resources flow log ID | diff --git a/examples/flow-logs/main.tf b/examples/flow-logs/main.tf new file mode 100644 index 0000000..9e07095 --- /dev/null +++ b/examples/flow-logs/main.tf @@ -0,0 +1,298 @@ +provider "aws" { + region = local.region +} + +locals { + name = "ex-tgw-flow-logs-${replace(basename(path.cwd), "_", "-")}" + region = "eu-west-1" + + tags = { + Example = local.name + GithubRepo = "terraform-aws-transit-gateway" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# Transit Gateway with CloudWatch Flow Logs +################################################################################ + +module "tgw_with_cloudwatch_logs" { + source = "../../" + + name = "${local.name}-cloudwatch" + description = "TGW with CloudWatch flow logs" + + # Enable flow logs to CloudWatch + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + # CloudWatch log group settings + flow_log_cloudwatch_log_group_name_prefix = "/aws/transit-gateway/flowlogs/" + flow_log_cloudwatch_log_group_retention_in_days = 30 + flow_log_cloudwatch_log_group_kms_key_id = aws_kms_key.log_encryption.arn + + # Flow log settings + flow_log_traffic_type = "ALL" + flow_log_max_aggregation_interval = 60 + flow_log_log_format = "$${version} $${account-id} $${transit-gateway-id} $${transit-gateway-attachment-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${windowstart} $${windowend} $${action}" + + vpc_attachments = { + vpc1 = { + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + } + vpc2 = { + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + } + } + + tgw_flow_log_tags = { + LogType = "TransitGatewayFlow" + Destination = "CloudWatch" + } + + tags = local.tags +} + +################################################################################ +# Transit Gateway with S3 Flow Logs +################################################################################ + +module "tgw_with_s3_logs" { + source = "../../" + + name = "${local.name}-s3" + description = "TGW with S3 flow logs" + + # Enable flow logs to S3 + enable_flow_log = true + flow_log_destination_type = "s3" + flow_log_destination_arn = aws_s3_bucket.flow_logs.arn + + # S3 destination options + flow_log_file_format = "parquet" + flow_log_hive_compatible_partitions = true + flow_log_per_hour_partition = true + + # Flow log settings + flow_log_traffic_type = "ALL" + flow_log_max_aggregation_interval = 600 + + vpc_attachments = { + vpc1 = { + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + } + } + + tgw_flow_log_tags = { + LogType = "TransitGatewayFlow" + Destination = "S3" + } + + tags = local.tags +} + +################################################################################ +# Transit Gateway with External Resources +################################################################################ + +module "tgw_with_external_resources" { + source = "../../" + + name = "${local.name}-external" + description = "TGW with external flow log resources" + + # Enable flow logs using external resources + enable_flow_log = true + create_flow_log_cloudwatch_log_group = false + create_flow_log_cloudwatch_iam_role = false + + # Use external resources + flow_log_destination_arn = aws_cloudwatch_log_group.external.arn + flow_log_cloudwatch_iam_role_arn = aws_iam_role.external.arn + + # Flow log settings + flow_log_traffic_type = "REJECT" + flow_log_max_aggregation_interval = 60 + + vpc_attachments = { + vpc2 = { + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + } + } + + tgw_flow_log_tags = { + LogType = "TransitGatewayFlow" + Destination = "CloudWatchExternal" + } + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +# VPCs for demonstration +module "vpc1" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = "${local.name}-vpc1" + cidr = "10.10.0.0/16" + + azs = ["${local.region}a", "${local.region}b"] + private_subnets = ["10.10.1.0/24", "10.10.2.0/24"] + + tags = local.tags +} + +module "vpc2" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = "${local.name}-vpc2" + cidr = "10.20.0.0/16" + + azs = ["${local.region}a", "${local.region}b"] + private_subnets = ["10.20.1.0/24", "10.20.2.0/24"] + + tags = local.tags +} + +# KMS key for CloudWatch log encryption +resource "aws_kms_key" "log_encryption" { + description = "KMS key for Transit Gateway flow logs encryption" + + tags = merge(local.tags, { + Name = "${local.name}-log-encryption" + }) +} + +resource "aws_kms_alias" "log_encryption" { + name = "alias/${local.name}-log-encryption" + target_key_id = aws_kms_key.log_encryption.key_id +} + +# S3 bucket for flow logs +resource "aws_s3_bucket" "flow_logs" { + bucket = "${local.name}-flow-logs-${random_id.bucket_suffix.hex}" + force_destroy = true + + tags = merge(local.tags, { + Name = "${local.name}-flow-logs" + }) +} + +resource "random_id" "bucket_suffix" { + byte_length = 4 +} + +resource "aws_s3_bucket_policy" "flow_logs" { + bucket = aws_s3_bucket.flow_logs.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AWSLogDeliveryWrite" + Effect = "Allow" + Principal = { + Service = "delivery.logs.amazonaws.com" + } + Action = "s3:PutObject" + Resource = "${aws_s3_bucket.flow_logs.arn}/*" + Condition = { + StringEquals = { + "s3:x-amz-acl" = "bucket-owner-full-control" + } + } + }, + { + Sid = "AWSLogDeliveryAclCheck" + Effect = "Allow" + Principal = { + Service = "delivery.logs.amazonaws.com" + } + Action = "s3:GetBucketAcl" + Resource = aws_s3_bucket.flow_logs.arn + } + ] + }) +} + +resource "aws_s3_bucket_versioning" "flow_logs" { + bucket = aws_s3_bucket.flow_logs.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "flow_logs" { + bucket = aws_s3_bucket.flow_logs.id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } +} + +# External CloudWatch log group +resource "aws_cloudwatch_log_group" "external" { + name = "/aws/transit-gateway/external/${local.name}" + retention_in_days = 7 + kms_key_id = aws_kms_key.log_encryption.arn + + tags = merge(local.tags, { + Name = "${local.name}-external-log-group" + }) +} + +# External IAM role for flow logs +resource "aws_iam_role" "external" { + name = "${local.name}-external-flow-log-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "vpc-flow-logs.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) + + tags = merge(local.tags, { + Name = "${local.name}-external-flow-log-role" + }) +} + +resource "aws_iam_role_policy" "external" { + name = "${local.name}-external-flow-log-policy" + role = aws_iam_role.external.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams" + ] + Resource = "${aws_cloudwatch_log_group.external.arn}:*" + } + ] + }) +} diff --git a/examples/flow-logs/outputs.tf b/examples/flow-logs/outputs.tf new file mode 100644 index 0000000..e73e289 --- /dev/null +++ b/examples/flow-logs/outputs.tf @@ -0,0 +1,105 @@ +################################################################################ +# Transit Gateway Flow Logs - CloudWatch +################################################################################ + +output "tgw_flow_log_cloudwatch_id" { + description = "CloudWatch flow log ID" + value = module.tgw_with_cloudwatch_logs.tgw_flow_log_id +} + +output "tgw_flow_log_cloudwatch_destination_arn" { + description = "CloudWatch flow log destination ARN" + value = module.tgw_with_cloudwatch_logs.tgw_flow_log_destination_arn +} + +output "tgw_flow_log_cloudwatch_iam_role_arn" { + description = "CloudWatch flow log IAM role ARN" + value = module.tgw_with_cloudwatch_logs.tgw_flow_log_cloudwatch_iam_role_arn +} + +output "tgw_cloudwatch_id" { + description = "CloudWatch TGW ID" + value = module.tgw_with_cloudwatch_logs.ec2_transit_gateway_id +} + +################################################################################ +# Transit Gateway Flow Logs - S3 +################################################################################ + +output "tgw_flow_log_s3_id" { + description = "S3 flow log ID" + value = module.tgw_with_s3_logs.tgw_flow_log_id +} + +output "tgw_flow_log_s3_destination_arn" { + description = "S3 flow log destination ARN" + value = module.tgw_with_s3_logs.tgw_flow_log_destination_arn +} + +output "tgw_s3_id" { + description = "S3 TGW ID" + value = module.tgw_with_s3_logs.ec2_transit_gateway_id +} + +output "s3_bucket_name" { + description = "S3 bucket name for flow logs" + value = aws_s3_bucket.flow_logs.bucket +} + +output "s3_bucket_arn" { + description = "S3 bucket ARN for flow logs" + value = aws_s3_bucket.flow_logs.arn +} + +################################################################################ +# Transit Gateway Flow Logs - External Resources +################################################################################ + +output "tgw_flow_log_external_id" { + description = "External resources flow log ID" + value = module.tgw_with_external_resources.tgw_flow_log_id +} + +output "tgw_flow_log_external_destination_arn" { + description = "External flow log destination ARN" + value = module.tgw_with_external_resources.tgw_flow_log_destination_arn +} + +output "tgw_external_id" { + description = "External TGW ID" + value = module.tgw_with_external_resources.ec2_transit_gateway_id +} + +output "external_log_group_name" { + description = "External CloudWatch log group name" + value = aws_cloudwatch_log_group.external.name +} + +output "external_iam_role_arn" { + description = "External IAM role ARN" + value = aws_iam_role.external.arn +} + +################################################################################ +# Supporting Resources +################################################################################ + +output "kms_key_id" { + description = "KMS key ID for log encryption" + value = aws_kms_key.log_encryption.id +} + +output "kms_key_arn" { + description = "KMS key ARN for log encryption" + value = aws_kms_key.log_encryption.arn +} + +output "vpc1_id" { + description = "VPC1 ID" + value = module.vpc1.vpc_id +} + +output "vpc2_id" { + description = "VPC2 ID" + value = module.vpc2.vpc_id +} diff --git a/examples/flow-logs/variables.tf b/examples/flow-logs/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/flow-logs/versions.tf b/examples/flow-logs/versions.tf new file mode 100644 index 0000000..3ce2f0e --- /dev/null +++ b/examples/flow-logs/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 0.13.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.4" + } + random = { + source = "hashicorp/random" + version = ">= 3.1" + } + } +} diff --git a/outputs.tf b/outputs.tf index 8dcb8a5..6e8e83e 100644 --- a/outputs.tf +++ b/outputs.tf @@ -98,3 +98,32 @@ output "ram_principal_association_id" { description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" value = try(aws_ram_principal_association.this[0].id, "") } + +################################################################################ +# Flow Log +################################################################################ + +output "tgw_flow_log_id" { + description = "The ID of the Flow Log resource" + value = try(aws_flow_log.this[0].id, null) +} + +output "tgw_flow_log_destination_arn" { + description = "The ARN of the destination for TGW Flow Logs" + value = local.flow_log_destination_arn +} + +output "tgw_flow_log_destination_type" { + description = "The type of the destination for TGW Flow Logs" + value = var.flow_log_destination_type +} + +output "tgw_flow_log_cloudwatch_iam_role_arn" { + description = "The ARN of the IAM role used when pushing logs to Cloudwatch log group" + value = local.flow_log_iam_role_arn +} + +output "tgw_flow_log_deliver_cross_account_role" { + description = "The ARN of the IAM role used when pushing logs cross account" + value = try(aws_flow_log.this[0].deliver_cross_account_role, null) +} diff --git a/tgw-flow-logs.tf b/tgw-flow-logs.tf new file mode 100644 index 0000000..8ad3847 --- /dev/null +++ b/tgw-flow-logs.tf @@ -0,0 +1,148 @@ +data "aws_region" "current" { + # Call this API only if create_tgw and enable_flow_log are true + count = var.create_tgw && var.enable_flow_log ? 1 : 0 +} + +data "aws_caller_identity" "current" { + # Call this API only if create_tgw and enable_flow_log are true + count = var.create_tgw && var.enable_flow_log ? 1 : 0 +} + +data "aws_partition" "current" { + # Call this API only if create_tgw and enable_flow_log are true + count = var.create_tgw && var.enable_flow_log ? 1 : 0 +} + +locals { + # Only create flow log if user selected to create a TGW as well + enable_flow_log = var.create_tgw && var.enable_flow_log + + create_flow_log_cloudwatch_iam_role = local.enable_flow_log && var.flow_log_destination_type != "s3" && var.create_flow_log_cloudwatch_iam_role + create_flow_log_cloudwatch_log_group = local.enable_flow_log && var.flow_log_destination_type != "s3" && var.create_flow_log_cloudwatch_log_group + + flow_log_destination_arn = local.create_flow_log_cloudwatch_log_group ? try(aws_cloudwatch_log_group.flow_log[0].arn, null) : var.flow_log_destination_arn + flow_log_iam_role_arn = var.flow_log_destination_type != "s3" && local.create_flow_log_cloudwatch_iam_role ? try(aws_iam_role.tgw_flow_log_cloudwatch[0].arn, null) : var.flow_log_cloudwatch_iam_role_arn + flow_log_cloudwatch_log_group_name_suffix = var.flow_log_cloudwatch_log_group_name_suffix == "" ? var.create_tgw ? aws_ec2_transit_gateway.this[0].id : var.name : var.flow_log_cloudwatch_log_group_name_suffix + flow_log_group_arns = [ + for log_group in aws_cloudwatch_log_group.flow_log : + "arn:${data.aws_partition.current[0].partition}:logs:${data.aws_region.current[0].region}:${data.aws_caller_identity.current[0].account_id}:log-group:${log_group.name}:*" + ] +} + +################################################################################ +# Flow Log +################################################################################ + +resource "aws_flow_log" "this" { + count = local.enable_flow_log ? 1 : 0 + + log_destination_type = var.flow_log_destination_type + log_destination = local.flow_log_destination_arn + log_format = var.flow_log_log_format + iam_role_arn = local.flow_log_iam_role_arn + deliver_cross_account_role = var.flow_log_deliver_cross_account_role + traffic_type = var.flow_log_traffic_type + transit_gateway_id = var.create_tgw ? aws_ec2_transit_gateway.this[0].id : null + max_aggregation_interval = var.flow_log_max_aggregation_interval + + dynamic "destination_options" { + for_each = var.flow_log_destination_type == "s3" ? [true] : [] + + content { + file_format = var.flow_log_file_format + hive_compatible_partitions = var.flow_log_hive_compatible_partitions + per_hour_partition = var.flow_log_per_hour_partition + } + } + + tags = merge(var.tags, var.tgw_flow_log_tags) +} + +################################################################################ +# Flow Log CloudWatch +################################################################################ + +resource "aws_cloudwatch_log_group" "flow_log" { + count = local.create_flow_log_cloudwatch_log_group ? 1 : 0 + + name = "${var.flow_log_cloudwatch_log_group_name_prefix}${local.flow_log_cloudwatch_log_group_name_suffix}" + retention_in_days = var.flow_log_cloudwatch_log_group_retention_in_days + kms_key_id = var.flow_log_cloudwatch_log_group_kms_key_id + skip_destroy = var.flow_log_cloudwatch_log_group_skip_destroy + log_group_class = var.flow_log_cloudwatch_log_group_class + + tags = merge(var.tags, var.tgw_flow_log_tags) +} + +resource "aws_iam_role" "tgw_flow_log_cloudwatch" { + count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 + + name = var.tgw_flow_log_iam_role_use_name_prefix ? null : var.tgw_flow_log_iam_role_name + name_prefix = var.tgw_flow_log_iam_role_use_name_prefix ? "${var.tgw_flow_log_iam_role_name}-" : null + + assume_role_policy = data.aws_iam_policy_document.flow_log_cloudwatch_assume_role[0].json + permissions_boundary = var.tgw_flow_log_permissions_boundary + + tags = merge(var.tags, var.tgw_flow_log_tags) +} + +data "aws_iam_policy_document" "flow_log_cloudwatch_assume_role" { + count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 + + statement { + sid = "AWSTGWFlowLogsAssumeRole" + + principals { + type = "Service" + identifiers = ["vpc-flow-logs.amazonaws.com"] + } + + effect = "Allow" + + actions = ["sts:AssumeRole"] + + dynamic "condition" { + for_each = var.flow_log_cloudwatch_iam_role_conditions + content { + test = condition.value.test + variable = condition.value.variable + values = condition.value.values + } + } + } +} + +resource "aws_iam_role_policy_attachment" "tgw_flow_log_cloudwatch" { + count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 + + role = aws_iam_role.tgw_flow_log_cloudwatch[0].name + policy_arn = aws_iam_policy.tgw_flow_log_cloudwatch[0].arn +} + +resource "aws_iam_policy" "tgw_flow_log_cloudwatch" { + count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 + + name = var.tgw_flow_log_iam_policy_use_name_prefix ? null : var.tgw_flow_log_iam_policy_name + name_prefix = var.tgw_flow_log_iam_policy_use_name_prefix ? "${var.tgw_flow_log_iam_policy_name}-" : null + policy = data.aws_iam_policy_document.tgw_flow_log_cloudwatch[0].json + tags = merge(var.tags, var.tgw_flow_log_tags) +} + +data "aws_iam_policy_document" "tgw_flow_log_cloudwatch" { + count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 + + statement { + sid = "AWSTGWFlowLogsPushToCloudWatch" + + effect = "Allow" + + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + ] + + resources = local.flow_log_group_arns + } +} diff --git a/variables.tf b/variables.tf index da01c9d..38fe70c 100644 --- a/variables.tf +++ b/variables.tf @@ -175,3 +175,167 @@ variable "ram_tags" { type = map(string) default = {} } + +################################################################################ +# Flow Log +################################################################################ + +variable "enable_flow_log" { + description = "Whether or not to enable TGW Flow Logs" + type = bool + default = false +} + +variable "create_flow_log_cloudwatch_iam_role" { + description = "Whether to create IAM role for TGW Flow Logs" + type = bool + default = false +} + +variable "create_flow_log_cloudwatch_log_group" { + description = "Whether to create CloudWatch log group for TGW Flow Logs" + type = bool + default = false +} + +variable "flow_log_destination_type" { + description = "Type of flow log destination. Can be s3, kinesis-data-firehose or cloud-watch-logs" + type = string + default = "cloud-watch-logs" +} + +variable "flow_log_destination_arn" { + description = "The ARN of the CloudWatch log group or S3 bucket where TGW Flow Logs will be pushed. If this ARN is a S3 bucket the appropriate permissions need to be set on that bucket's policy. When create_flow_log_cloudwatch_log_group is set to false this argument must be provided" + type = string + default = "" +} + +variable "flow_log_log_format" { + description = "The fields to include in the flow log record, in the order in which they should appear" + type = string + default = null +} + +variable "flow_log_traffic_type" { + description = "The type of traffic to capture. Valid values: ACCEPT, REJECT, ALL" + type = string + default = "ALL" +} + +variable "flow_log_max_aggregation_interval" { + description = "The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: `60` seconds" + type = number + default = 60 +} + +variable "flow_log_deliver_cross_account_role" { + description = "(Optional) ARN of the IAM role that allows Amazon EC2 to publish flow logs across accounts." + type = string + default = null +} + +variable "flow_log_file_format" { + description = "(Optional) The format for the flow log. Valid values: `plain-text`, `parquet`" + type = string + default = null +} + +variable "flow_log_hive_compatible_partitions" { + description = "(Optional) Indicates whether to use Hive-compatible prefixes for flow logs stored in Amazon S3" + type = bool + default = false +} + +variable "flow_log_per_hour_partition" { + description = "(Optional) Indicates whether to partition the flow log per hour. This reduces the cost and response time for queries" + type = bool + default = false +} + +variable "flow_log_cloudwatch_iam_role_arn" { + description = "The ARN for the IAM role that's used to post flow logs to a CloudWatch Logs log group. When flow_log_destination_arn is set to ARN of Cloudwatch Logs, this argument needs to be provided" + type = string + default = "" +} + +variable "flow_log_cloudwatch_iam_role_conditions" { + description = "Additional conditions of the CloudWatch role assumption policy" + type = list(object({ + test = string + variable = string + values = list(string) + })) + default = [] +} + +variable "flow_log_cloudwatch_log_group_name_prefix" { + description = "Specifies the name prefix of CloudWatch Log Group for TGW flow logs" + type = string + default = "/aws/tgw-flow-log/" +} + +variable "flow_log_cloudwatch_log_group_name_suffix" { + description = "Specifies the name suffix of CloudWatch Log Group for TGW flow logs" + type = string + default = "" +} + +variable "flow_log_cloudwatch_log_group_retention_in_days" { + description = "Specifies the number of days you want to retain log events in the specified log group for TGW flow logs" + type = number + default = null +} + +variable "flow_log_cloudwatch_log_group_kms_key_id" { + description = "The ARN of the KMS Key to use when encrypting log data for TGW flow logs" + type = string + default = null +} + +variable "flow_log_cloudwatch_log_group_skip_destroy" { + description = "Set to true if you do not wish the log group (and any logs it may contain) to be deleted at destroy time, and instead just remove the log group from the Terraform state" + type = bool + default = false +} + +variable "flow_log_cloudwatch_log_group_class" { + description = "Specified the log class of the log group. Possible values are: STANDARD or INFREQUENT_ACCESS" + type = string + default = null +} + +variable "tgw_flow_log_iam_role_name" { + description = "Name to use on the TGW Flow Log IAM role created" + type = string + default = "tgw-flow-log-role" +} + +variable "tgw_flow_log_iam_role_use_name_prefix" { + description = "Determines whether the IAM role name (`tgw_flow_log_iam_role_name`) is used as a prefix" + type = bool + default = true +} + +variable "tgw_flow_log_permissions_boundary" { + description = "The ARN of the Permissions Boundary for the TGW Flow Log IAM Role" + type = string + default = null +} + +variable "tgw_flow_log_iam_policy_name" { + description = "Name of the IAM policy" + type = string + default = "tgw-flow-log-to-cloudwatch" +} + +variable "tgw_flow_log_iam_policy_use_name_prefix" { + description = "Determines whether the name of the IAM policy (`tgw_flow_log_iam_policy_name`) is used as a prefix" + type = bool + default = true +} + +variable "tgw_flow_log_tags" { + description = "Additional tags for the TGW Flow Logs" + type = map(string) + default = {} +}
test = string
variable = string
values = list(string)
}))