diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 6b6c9cec0..bd5f2df7c 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -8,7 +8,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v4 + - uses: dessant/lock-threads@v5 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-comment: > diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index cb32a0f81..3973df443 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -14,7 +14,7 @@ jobs: steps: # Please look up the latest version from # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@v5.0.2 + - uses: amannn/action-semantic-pull-request@v5.4.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index cb8267134..c2632d1a4 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -8,7 +8,7 @@ on: env: TERRAFORM_DOCS_VERSION: v0.16.0 - TFLINT_VERSION: v0.44.1 + TFLINT_VERSION: v0.50.3 jobs: collectInputs: @@ -18,11 +18,11 @@ jobs: directories: ${{ steps.dirs.outputs.directories }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get root directories id: dirs - uses: clowdhaus/terraform-composite-actions/directories@v1.8.3 + uses: clowdhaus/terraform-composite-actions/directories@v1.9.0 preCommitMinVersions: name: Min TF pre-commit @@ -32,19 +32,27 @@ jobs: matrix: directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Terraform min/max versions id: minMax - uses: clowdhaus/terraform-min-max@v1.2.4 + uses: clowdhaus/terraform-min-max@v1.3.0 with: directory: ${{ matrix.directory }} - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} # Run only validate pre-commit check on min version supported if: ${{ matrix.directory != '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.9.0 with: terraform-version: ${{ steps.minMax.outputs.minVersion }} tflint-version: ${{ env.TFLINT_VERSION }} @@ -53,7 +61,7 @@ jobs: - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} # Run only validate pre-commit check on min version supported if: ${{ matrix.directory == '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.9.0 with: terraform-version: ${{ steps.minMax.outputs.minVersion }} tflint-version: ${{ env.TFLINT_VERSION }} @@ -64,18 +72,26 @@ jobs: runs-on: ubuntu-latest needs: collectInputs steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{github.event.pull_request.head.repo.full_name}} - name: Terraform min/max versions id: minMax - uses: clowdhaus/terraform-min-max@v1.2.4 + uses: clowdhaus/terraform-min-max@v1.3.0 - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.9.0 with: terraform-version: ${{ steps.minMax.outputs.maxVersion }} tflint-version: ${{ env.TFLINT_VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81f674740..4a9422614 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,18 +20,18 @@ jobs: if: github.repository_owner == 'terraform-aws-modules' steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false fetch-depth: 0 - name: Release - uses: cycjimmy/semantic-release-action@v3 + uses: cycjimmy/semantic-release-action@v4 with: - semantic_version: 18.0.0 + semantic_version: 23.0.2 extra_plugins: | - @semantic-release/changelog@6.0.0 - @semantic-release/git@10.0.0 - conventional-changelog-conventionalcommits@4.6.3 + @semantic-release/changelog@6.0.3 + @semantic-release/git@10.0.1 + conventional-changelog-conventionalcommits@7.0.2 env: GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} diff --git a/.github/workflows/stale-actions.yaml b/.github/workflows/stale-actions.yaml index 50379957f..6ccd0ed85 100644 --- a/.github/workflows/stale-actions.yaml +++ b/.github/workflows/stale-actions.yaml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Staling issues and PR's diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f3428382..3418005ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,8 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.81.0 + rev: v1.92.1 hooks: - id: terraform_fmt - - id: terraform_validate - id: terraform_docs args: - '--args=--lockfile=false' @@ -22,8 +21,11 @@ repos: - '--args=--only=terraform_required_providers' - '--args=--only=terraform_standard_module_structure' - '--args=--only=terraform_workspace_remote' + - '--args=--only=terraform_unused_required_providers' + - id: terraform_validate - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: check-merge-conflict - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/.spacelift/config.yml b/.spacelift/config.yml index 4aae5459a..ce65ee521 100644 --- a/.spacelift/config.yml +++ b/.spacelift/config.yml @@ -1,2 +1,2 @@ version: 1 -module_version: 5.1.1 +module_version: 1.0.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a37073a..dd1d2be57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,132 @@ All notable changes to this project will be documented in this file. +## [5.12.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.11.0...v5.12.0) (2024-08-03) + + +### Features + +* Restrict flow log policy to use log group ARNs ([#1088](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1088)) ([9256722](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/92567225dc73ef939b86a241b9607cb13329fb75)) + +## [5.11.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.10.0...v5.11.0) (2024-08-03) + + +### Features + +* Add route to `0.0.0.0/0` & `::/0` (when IPv6 is enabled) on all public route tables ([#1100](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1100)) ([b3e7803](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/b3e78033bbee8346341a523f78f762ade41eb93b)) + +## [5.10.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.9.0...v5.10.0) (2024-08-02) + + +### Features + +* Added ipv6_address_preferred_lease_time parameter to aws_vpc_dhcp_options resource ([#1105](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1105)) ([3adb594](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/3adb594bc794468c80a99c5c1808056a88767f45)) + +## [5.9.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.8.1...v5.9.0) (2024-07-05) + + +### Features + +* Allow custom VPC Flow Log IAM Role name and IAM Policy name ([#1089](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1089)) ([f8cd168](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/f8cd1681837c8c4a24af6fe73035724a03e1e66e)) + +## [5.8.1](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.8.0...v5.8.1) (2024-04-26) + + +### Bug Fixes + +* Do not replace NAT gateways when additional subnets are added ([#1055](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1055)) ([cf18c37](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/cf18c37591f860908e2223b4f488787e8a5f74f3)) + +## [5.8.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.7.2...v5.8.0) (2024-04-25) + + +### Features + +* Add support for multiple route tables to public and intra subnets ([#1051](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1051)) ([da05f24](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/da05f24c5c603a31d320d5ad92493bb39fea9f3d)) + +## [5.7.2](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.7.1...v5.7.2) (2024-04-24) + + +### Bug Fixes + +* Create private_ipv6_egress routes only when having at least one private subnet ([#1062](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1062)) ([8701204](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/8701204c28a0ff984c5ade71400c6208c6953bfc)) + +## [5.7.1](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.7.0...v5.7.1) (2024-04-06) + + +### Bug Fixes + +* Create the same number of IPv6 egress only gateway routes as the number of NAT gateways that are enabled/created ([#1059](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1059)) ([77df552](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/77df552a8aa43bb3711243a3a5ef3e29f70a4068)) + +## [5.7.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.6.0...v5.7.0) (2024-03-22) + + +### Features + +* Allow setting vpc endpoints as an input for each endpoint ([#1056](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1056)) ([9163310](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/9163310db647ed98094319980bd8eef72bee492b)) + +## [5.6.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.5.3...v5.6.0) (2024-03-14) + + +### Features + +* Support VPC flow log cloudwatch log group class ([#1053](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1053)) ([e2970fd](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/e2970fd747bbf5d0b1539f7bbbdced56977a1bdf)) + +## [5.5.3](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.5.2...v5.5.3) (2024-03-06) + + +### Bug Fixes + +* Update CI workflow versions to remove deprecated runtime warnings ([#1052](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1052)) ([3b5b7f1](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/3b5b7f1fea768c6c933ea1ce2f8ee11250fa94cb)) + +### [5.5.2](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.5.1...v5.5.2) (2024-02-09) + + +### Bug Fixes + +* Added create_before_destroy to aws_customer_gateway ([#1036](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1036)) ([5f5df57](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/5f5df571925895ad1fdf5a3bd04e539aa13f5a1d)) + +### [5.5.1](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.5.0...v5.5.1) (2024-01-13) + + +### Bug Fixes + +* Correct VPC endpoint private DNS resolver `for_each` key ([#1029](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1029)) ([a837be1](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/a837be12882c8f74984620752937b4806da2d6d4)) + +## [5.5.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.4.0...v5.5.0) (2024-01-09) + + +### Features + +* Add support for `dns_options` on VPC endpoints ([#1023](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1023)) ([32f853f](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/32f853f4c099ad134d9c739d585c42a7c06a797b)) + +## [5.4.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.3.0...v5.4.0) (2023-12-11) + + +### Features + +* Add Cross Account Flow Support ([#1014](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1014)) ([6e25437](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/6e25437b16955b9393348d91965ead2f755fb2e0)) + +## [5.3.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.2.0...v5.3.0) (2023-12-11) + + +### Features + +* Add NAT gateway interface ids output ([#1006](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1006)) ([898bbaf](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/898bbaf46ba8ebad54983d63fa9e8eac6456903b)) + +## [5.2.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.1.2...v5.2.0) (2023-11-18) + + +### Features + +* Add `skip_destroy` to vpc flow log cloudwatch log group ([#1009](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/1009)) ([abe2c0f](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/abe2c0fcd23f1adfcb6e3a7739811e2482e2d197)) + +### [5.1.2](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.1.1...v5.1.2) (2023-09-07) + + +### Bug Fixes + +* The number of intra subnets should not influence the number of NAT gateways provisioned ([#968](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/968)) ([1e36f9f](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/1e36f9f8a01eb26be83d8e1ce2227a6890390b0e)) + ### [5.1.1](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v5.1.0...v5.1.1) (2023-07-25) diff --git a/README.md b/README.md index 73c591304..220ad3e80 100644 --- a/README.md +++ b/README.md @@ -256,13 +256,13 @@ Full contributing [guidelines are covered here](.github/contributing.md). | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules @@ -349,8 +349,10 @@ No modules. | [aws_vpn_gateway_route_propagation.intra](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_route_propagation) | resource | | [aws_vpn_gateway_route_propagation.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_route_propagation) | resource | | [aws_vpn_gateway_route_propagation.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_route_propagation) | 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.vpc_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -369,6 +371,8 @@ No modules. | [create\_flow\_log\_cloudwatch\_iam\_role](#input\_create\_flow\_log\_cloudwatch\_iam\_role) | Whether to create IAM role for VPC 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 VPC Flow Logs | `bool` | `false` | no | | [create\_igw](#input\_create\_igw) | Controls if an Internet Gateway is created for public subnets and the related routes that connect them | `bool` | `true` | no | +| [create\_multiple\_intra\_route\_tables](#input\_create\_multiple\_intra\_route\_tables) | Indicates whether to create a separate route table for each intra subnet. Default: `false` | `bool` | `false` | no | +| [create\_multiple\_public\_route\_tables](#input\_create\_multiple\_public\_route\_tables) | Indicates whether to create a separate route table for each public subnet. Default: `false` | `bool` | `false` | no | | [create\_redshift\_subnet\_group](#input\_create\_redshift\_subnet\_group) | Controls if redshift subnet group should be created | `bool` | `true` | no | | [create\_redshift\_subnet\_route\_table](#input\_create\_redshift\_subnet\_route\_table) | Controls if separate route table for redshift should be created | `bool` | `false` | no | | [create\_vpc](#input\_create\_vpc) | Controls if VPC should be created (it affects almost all resources) | `bool` | `true` | no | @@ -411,6 +415,7 @@ No modules. | [default\_vpc\_tags](#input\_default\_vpc\_tags) | Additional tags for the Default VPC | `map(string)` | `{}` | no | | [dhcp\_options\_domain\_name](#input\_dhcp\_options\_domain\_name) | Specifies DNS name for DHCP options set (requires enable\_dhcp\_options set to true) | `string` | `""` | no | | [dhcp\_options\_domain\_name\_servers](#input\_dhcp\_options\_domain\_name\_servers) | Specify a list of DNS server addresses for DHCP options set, default to AWS provided (requires enable\_dhcp\_options set to true) | `list(string)` |
[
"AmazonProvidedDNS"
]
| no | +| [dhcp\_options\_ipv6\_address\_preferred\_lease\_time](#input\_dhcp\_options\_ipv6\_address\_preferred\_lease\_time) | How frequently, in seconds, a running instance with an IPv6 assigned to it goes through DHCPv6 lease renewal (requires enable\_dhcp\_options set to true) | `number` | `null` | no | | [dhcp\_options\_netbios\_name\_servers](#input\_dhcp\_options\_netbios\_name\_servers) | Specify a list of netbios servers for DHCP options set (requires enable\_dhcp\_options set to true) | `list(string)` | `[]` | no | | [dhcp\_options\_netbios\_node\_type](#input\_dhcp\_options\_netbios\_node\_type) | Specify netbios node\_type for DHCP options set (requires enable\_dhcp\_options set to true) | `string` | `""` | no | | [dhcp\_options\_ntp\_servers](#input\_dhcp\_options\_ntp\_servers) | Specify a list of NTP servers for DHCP options set (requires enable\_dhcp\_options set to true) | `list(string)` | `[]` | no | @@ -445,12 +450,15 @@ No modules. | [external\_nat\_ip\_ids](#input\_external\_nat\_ip\_ids) | List of EIP IDs to be assigned to the NAT Gateways (used in combination with reuse\_nat\_ips) | `list(string)` | `[]` | no | | [external\_nat\_ips](#input\_external\_nat\_ips) | List of EIPs to be used for `nat_public_ips` output (used in combination with reuse\_nat\_ips and external\_nat\_ip\_ids) | `list(string)` | `[]` | 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\_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 VPC 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 VPC flow logs | `string` | `"/aws/vpc-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 VPC 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 VPC 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 VPC 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 or cloud-watch-logs | `string` | `"cloud-watch-logs"` | 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 | @@ -570,6 +578,10 @@ No modules. | [single\_nat\_gateway](#input\_single\_nat\_gateway) | Should be true if you want to provision a single shared NAT Gateway across all of your private networks | `bool` | `false` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [use\_ipam\_pool](#input\_use\_ipam\_pool) | Determines whether IPAM pool is used for CIDR allocation | `bool` | `false` | no | +| [vpc\_flow\_log\_iam\_policy\_name](#input\_vpc\_flow\_log\_iam\_policy\_name) | Name of the IAM policy | `string` | `"vpc-flow-log-to-cloudwatch"` | no | +| [vpc\_flow\_log\_iam\_policy\_use\_name\_prefix](#input\_vpc\_flow\_log\_iam\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`vpc_flow_log_iam_policy_name`) is used as a prefix | `bool` | `true` | no | +| [vpc\_flow\_log\_iam\_role\_name](#input\_vpc\_flow\_log\_iam\_role\_name) | Name to use on the VPC Flow Log IAM role created | `string` | `"vpc-flow-log-role"` | no | +| [vpc\_flow\_log\_iam\_role\_use\_name\_prefix](#input\_vpc\_flow\_log\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`vpc_flow_log_iam_role_name_name`) is used as a prefix | `bool` | `true` | no | | [vpc\_flow\_log\_permissions\_boundary](#input\_vpc\_flow\_log\_permissions\_boundary) | The ARN of the Permissions Boundary for the VPC Flow Log IAM Role | `string` | `null` | no | | [vpc\_flow\_log\_tags](#input\_vpc\_flow\_log\_tags) | Additional tags for the VPC Flow Logs | `map(string)` | `{}` | no | | [vpc\_tags](#input\_vpc\_tags) | Additional tags for the VPC | `map(string)` | `{}` | no | @@ -636,6 +648,7 @@ No modules. | [nat\_ids](#output\_nat\_ids) | List of allocation ID of Elastic IPs created for AWS NAT Gateway | | [nat\_public\_ips](#output\_nat\_public\_ips) | List of public Elastic IPs created for AWS NAT Gateway | | [natgw\_ids](#output\_natgw\_ids) | List of NAT Gateway IDs | +| [natgw\_interface\_ids](#output\_natgw\_interface\_ids) | List of Network Interface IDs assigned to NAT Gateways | | [outpost\_network\_acl\_arn](#output\_outpost\_network\_acl\_arn) | ARN of the outpost network ACL | | [outpost\_network\_acl\_id](#output\_outpost\_network\_acl\_id) | ID of the outpost network ACL | | [outpost\_subnet\_arns](#output\_outpost\_subnet\_arns) | List of ARNs of outpost subnets | @@ -680,6 +693,7 @@ No modules. | [vpc\_enable\_dns\_hostnames](#output\_vpc\_enable\_dns\_hostnames) | Whether or not the VPC has DNS hostname support | | [vpc\_enable\_dns\_support](#output\_vpc\_enable\_dns\_support) | Whether or not the VPC has DNS support | | [vpc\_flow\_log\_cloudwatch\_iam\_role\_arn](#output\_vpc\_flow\_log\_cloudwatch\_iam\_role\_arn) | The ARN of the IAM role used when pushing logs to Cloudwatch log group | +| [vpc\_flow\_log\_deliver\_cross\_account\_role](#output\_vpc\_flow\_log\_deliver\_cross\_account\_role) | The ARN of the IAM role used when pushing logs cross account | | [vpc\_flow\_log\_destination\_arn](#output\_vpc\_flow\_log\_destination\_arn) | The ARN of the destination for VPC Flow Logs | | [vpc\_flow\_log\_destination\_type](#output\_vpc\_flow\_log\_destination\_type) | The type of the destination for VPC Flow Logs | | [vpc\_flow\_log\_id](#output\_vpc\_flow\_log\_id) | The ID of the Flow Log resource | diff --git a/examples/complete/README.md b/examples/complete/README.md index d6e4eb4a8..7def7d8cd 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -22,13 +22,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 514355631..ccfcb4490 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -25,7 +25,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs @@ -73,10 +73,12 @@ module "vpc" { dhcp_options_domain_name_servers = ["127.0.0.1", "10.10.0.2"] # VPC Flow Logs (Cloudwatch log group and IAM role will be created) - enable_flow_log = true - create_flow_log_cloudwatch_log_group = true - create_flow_log_cloudwatch_iam_role = true - flow_log_max_aggregation_interval = 60 + vpc_flow_log_iam_role_name = "vpc-complete-example-role" + vpc_flow_log_iam_role_use_name_prefix = false + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + flow_log_max_aggregation_interval = 60 tags = local.tags } @@ -102,8 +104,12 @@ module "vpc_endpoints" { endpoints = { s3 = { - service = "s3" - tags = { Name = "s3-vpc-endpoint" } + service = "s3" + private_dns_enabled = true + dns_options = { + private_dns_only_for_inbound_resolver_endpoint = false + } + tags = { Name = "s3-vpc-endpoint" } }, dynamodb = { service = "dynamodb" diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/ipam/README.md b/examples/ipam/README.md index 07373875a..ce46e8091 100644 --- a/examples/ipam/README.md +++ b/examples/ipam/README.md @@ -30,13 +30,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/ipam/main.tf b/examples/ipam/main.tf index d43851202..b38186d02 100644 --- a/examples/ipam/main.tf +++ b/examples/ipam/main.tf @@ -26,7 +26,7 @@ locals { module "vpc_ipam_set_netmask" { source = "../.." - name = "${local.name}-set-netmask" + name_prefix = "${local.name}-set-netmask" use_ipam_pool = true ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id @@ -46,7 +46,7 @@ module "vpc_ipam_set_netmask" { module "vpc_ipam_set_cidr" { source = "../.." - name = "${local.name}-set-cidr" + name_prefix = "${local.name}-set-cidr" use_ipam_pool = true ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id diff --git a/examples/ipam/versions.tf b/examples/ipam/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/ipam/versions.tf +++ b/examples/ipam/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/ipv6-dualstack/README.md b/examples/ipv6-dualstack/README.md index 3318683ec..6ba90b025 100644 --- a/examples/ipv6-dualstack/README.md +++ b/examples/ipv6-dualstack/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/ipv6-dualstack/main.tf b/examples/ipv6-dualstack/main.tf index d71f8fe35..b514ff83f 100644 --- a/examples/ipv6-dualstack/main.tf +++ b/examples/ipv6-dualstack/main.tf @@ -25,7 +25,7 @@ locals { module "vpc" { source = "../.." - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs diff --git a/examples/ipv6-dualstack/versions.tf b/examples/ipv6-dualstack/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/ipv6-dualstack/versions.tf +++ b/examples/ipv6-dualstack/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/ipv6-only/README.md b/examples/ipv6-only/README.md index eb8cea2e0..8218895a2 100644 --- a/examples/ipv6-only/README.md +++ b/examples/ipv6-only/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/ipv6-only/main.tf b/examples/ipv6-only/main.tf index ba737316d..250d0092c 100644 --- a/examples/ipv6-only/main.tf +++ b/examples/ipv6-only/main.tf @@ -22,7 +22,7 @@ locals { module "vpc" { source = "../.." - name = local.name + name_prefix = local.name azs = slice(data.aws_availability_zones.available.names, 0, 3) enable_ipv6 = true diff --git a/examples/ipv6-only/versions.tf b/examples/ipv6-only/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/ipv6-only/versions.tf +++ b/examples/ipv6-only/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/issues/README.md b/examples/issues/README.md index 92cc3a4ca..b749be57b 100644 --- a/examples/issues/README.md +++ b/examples/issues/README.md @@ -25,13 +25,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/issues/main.tf b/examples/issues/main.tf index 9e23b806f..f3272e36f 100644 --- a/examples/issues/main.tf +++ b/examples/issues/main.tf @@ -24,7 +24,7 @@ locals { module "vpc_issue_44" { source = "../../" - name = "asymmetrical" + name_prefix = "asymmetrical" cidr = "10.0.0.0/16" azs = local.azs @@ -48,7 +48,7 @@ module "vpc_issue_44" { module "vpc_issue_46" { source = "../../" - name = "no-private-subnets" + name_prefix = "no-private-subnets" cidr = "10.0.0.0/16" azs = local.azs @@ -74,7 +74,7 @@ module "vpc_issue_46" { module "vpc_issue_108" { source = "../../" - name = "route-already-exists" + name_prefix = "route-already-exists" cidr = "10.0.0.0/16" azs = local.azs diff --git a/examples/issues/versions.tf b/examples/issues/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/issues/versions.tf +++ b/examples/issues/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/manage-default-vpc/README.md b/examples/manage-default-vpc/README.md index 0c506f33f..4f2c26e58 100644 --- a/examples/manage-default-vpc/README.md +++ b/examples/manage-default-vpc/README.md @@ -22,7 +22,7 @@ Run `terraform destroy` when you don't need these resources. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers diff --git a/examples/manage-default-vpc/versions.tf b/examples/manage-default-vpc/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/manage-default-vpc/versions.tf +++ b/examples/manage-default-vpc/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/network-acls/README.md b/examples/network-acls/README.md index 4e6ca7a0c..c0809311d 100644 --- a/examples/network-acls/README.md +++ b/examples/network-acls/README.md @@ -24,13 +24,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/network-acls/main.tf b/examples/network-acls/main.tf index 35c3a2211..fc2cc8243 100644 --- a/examples/network-acls/main.tf +++ b/examples/network-acls/main.tf @@ -174,7 +174,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs diff --git a/examples/network-acls/versions.tf b/examples/network-acls/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/network-acls/versions.tf +++ b/examples/network-acls/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/outpost/README.md b/examples/outpost/README.md index 8c7173bb9..87f5c8771 100644 --- a/examples/outpost/README.md +++ b/examples/outpost/README.md @@ -24,13 +24,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/outpost/main.tf b/examples/outpost/main.tf index b65e8d75a..adf3c6df8 100644 --- a/examples/outpost/main.tf +++ b/examples/outpost/main.tf @@ -124,7 +124,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs diff --git a/examples/outpost/versions.tf b/examples/outpost/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/outpost/versions.tf +++ b/examples/outpost/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/secondary-cidr-blocks/README.md b/examples/secondary-cidr-blocks/README.md index 5054d43f9..90632c1e7 100644 --- a/examples/secondary-cidr-blocks/README.md +++ b/examples/secondary-cidr-blocks/README.md @@ -22,13 +22,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/secondary-cidr-blocks/main.tf b/examples/secondary-cidr-blocks/main.tf index 5c963bb94..e4485ffc6 100644 --- a/examples/secondary-cidr-blocks/main.tf +++ b/examples/secondary-cidr-blocks/main.tf @@ -26,7 +26,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr secondary_cidr_blocks = local.secondary_cidr_blocks # can add up to 5 total CIDR blocks diff --git a/examples/secondary-cidr-blocks/versions.tf b/examples/secondary-cidr-blocks/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/secondary-cidr-blocks/versions.tf +++ b/examples/secondary-cidr-blocks/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/separate-route-tables/README.md b/examples/separate-route-tables/README.md index 57ee751f9..a5a93ab66 100644 --- a/examples/separate-route-tables/README.md +++ b/examples/separate-route-tables/README.md @@ -1,6 +1,6 @@ # VPC with separate private route tables -Configuration in this directory creates set of VPC resources which may be sufficient for staging or production environment (look into [simple-vpc](../simple-vpc) for more simplified setup). +Configuration in this directory creates set of VPC resources which may be sufficient for staging or production environment (look into [simple-vpc](../simple-vpc) for more simplified setup). There are public, private, database, ElastiCache, Redshift subnets, NAT Gateways created in each availability zone. **This example sets up separate private route for database, elasticache and redshift subnets.**. @@ -22,13 +22,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/separate-route-tables/main.tf b/examples/separate-route-tables/main.tf index 99cf9828f..2d661b6b5 100644 --- a/examples/separate-route-tables/main.tf +++ b/examples/separate-route-tables/main.tf @@ -25,7 +25,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs diff --git a/examples/separate-route-tables/versions.tf b/examples/separate-route-tables/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/separate-route-tables/versions.tf +++ b/examples/separate-route-tables/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/simple/README.md b/examples/simple/README.md index 0d5658b4a..0d661f54e 100644 --- a/examples/simple/README.md +++ b/examples/simple/README.md @@ -26,13 +26,13 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 324977173..e4c5a847d 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -25,7 +25,7 @@ locals { module "vpc" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs diff --git a/examples/simple/versions.tf b/examples/simple/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/examples/simple/versions.tf +++ b/examples/simple/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/examples/vpc-flow-logs/README.md b/examples/vpc-flow-logs/README.md index d0cb120a8..ad984edad 100644 --- a/examples/vpc-flow-logs/README.md +++ b/examples/vpc-flow-logs/README.md @@ -24,14 +24,14 @@ Note that this example may create resources which can cost money (AWS Elastic IP | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | | [random](#requirement\_random) | >= 2.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | | [random](#provider\_random) | >= 2.0 | ## Modules @@ -41,6 +41,7 @@ Note that this example may create resources which can cost money (AWS Elastic IP | [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | | [vpc\_with\_flow\_logs\_cloudwatch\_logs](#module\_vpc\_with\_flow\_logs\_cloudwatch\_logs) | ../../ | n/a | | [vpc\_with\_flow\_logs\_cloudwatch\_logs\_default](#module\_vpc\_with\_flow\_logs\_cloudwatch\_logs\_default) | ../../ | n/a | +| [vpc\_with\_flow\_logs\_cloudwatch\_logs\_prefix](#module\_vpc\_with\_flow\_logs\_cloudwatch\_logs\_prefix) | ../../ | n/a | | [vpc\_with\_flow\_logs\_s3\_bucket](#module\_vpc\_with\_flow\_logs\_s3\_bucket) | ../../ | n/a | | [vpc\_with\_flow\_logs\_s3\_bucket\_parquet](#module\_vpc\_with\_flow\_logs\_s3\_bucket\_parquet) | ../../ | n/a | diff --git a/examples/vpc-flow-logs/main.tf b/examples/vpc-flow-logs/main.tf index 140aa0cd6..4121dfdae 100644 --- a/examples/vpc-flow-logs/main.tf +++ b/examples/vpc-flow-logs/main.tf @@ -27,7 +27,7 @@ locals { module "vpc_with_flow_logs_s3_bucket" { source = "../../" - name = local.name + name_prefix = local.name cidr = local.vpc_cidr azs = local.azs @@ -44,7 +44,7 @@ module "vpc_with_flow_logs_s3_bucket" { module "vpc_with_flow_logs_s3_bucket_parquet" { source = "../../" - name = "${local.name}-parquet" + name_prefix = "${local.name}-parquet" cidr = local.vpc_cidr azs = local.azs @@ -63,7 +63,7 @@ module "vpc_with_flow_logs_s3_bucket_parquet" { module "vpc_with_flow_logs_cloudwatch_logs_default" { source = "../../" - name = "${local.name}-cloudwatch-logs-default" + name_prefix = "${local.name}-cloudwatch-logs-default" cidr = local.vpc_cidr azs = local.azs @@ -78,6 +78,36 @@ module "vpc_with_flow_logs_cloudwatch_logs_default" { flow_log_max_aggregation_interval = 60 flow_log_cloudwatch_log_group_name_prefix = "/aws/my-amazing-vpc-flow-logz/" flow_log_cloudwatch_log_group_name_suffix = "my-test" + flow_log_cloudwatch_log_group_class = "INFREQUENT_ACCESS" + + vpc_flow_log_tags = local.tags +} + +# CloudWatch Log Group and IAM prefix +module "vpc_with_flow_logs_cloudwatch_logs_prefix" { + source = "../../" + + name_prefix = "${local.name}-cloudwatch-logs-prefix" + cidr = local.vpc_cidr + + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 4)] + + # Cloudwatch log group and IAM role will be created + enable_flow_log = true + create_flow_log_cloudwatch_log_group = true + create_flow_log_cloudwatch_iam_role = true + + vpc_flow_log_iam_role_name = "vpc-iam-prefix-example" + vpc_flow_log_iam_role_use_name_prefix = true + vpc_flow_log_iam_policy_name = "vpc-iam-prefix-example" + vpc_flow_log_iam_policy_use_name_prefix = true + + flow_log_max_aggregation_interval = 60 + flow_log_cloudwatch_log_group_name_prefix = "/aws/my-amazing-vpc-flow-logz/" + flow_log_cloudwatch_log_group_name_suffix = "my-test" + flow_log_cloudwatch_log_group_class = "INFREQUENT_ACCESS" vpc_flow_log_tags = local.tags } @@ -86,7 +116,7 @@ module "vpc_with_flow_logs_cloudwatch_logs_default" { module "vpc_with_flow_logs_cloudwatch_logs" { source = "../../" - name = "${local.name}-cloudwatch-logs" + name_prefix = "${local.name}-cloudwatch-logs" cidr = local.vpc_cidr azs = local.azs diff --git a/examples/vpc-flow-logs/versions.tf b/examples/vpc-flow-logs/versions.tf index 383652286..35d5770de 100644 --- a/examples/vpc-flow-logs/versions.tf +++ b/examples/vpc-flow-logs/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } random = { diff --git a/main.tf b/main.tf index 25fb194e4..ed001e593 100644 --- a/main.tf +++ b/main.tf @@ -10,10 +10,10 @@ locals { max_subnet_length = max( local.len_private_subnets, local.len_public_subnets, - local.len_intra_subnets, local.len_elasticache_subnets, local.len_database_subnets, local.len_redshift_subnets, + local.len_tgw_subnets ) # Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free! @@ -45,7 +45,7 @@ resource "aws_vpc" "this" { enable_network_address_usage_metrics = var.enable_network_address_usage_metrics tags = merge( - { "Name" = var.name }, + { "Name" = "${var.name_prefix}-vpc${var.name_suffix}" }, var.tags, var.vpc_tags, ) @@ -67,14 +67,15 @@ resource "aws_vpc_ipv4_cidr_block_association" "this" { resource "aws_vpc_dhcp_options" "this" { count = local.create_vpc && var.enable_dhcp_options ? 1 : 0 - domain_name = var.dhcp_options_domain_name - domain_name_servers = var.dhcp_options_domain_name_servers - ntp_servers = var.dhcp_options_ntp_servers - netbios_name_servers = var.dhcp_options_netbios_name_servers - netbios_node_type = var.dhcp_options_netbios_node_type + domain_name = var.dhcp_options_domain_name + domain_name_servers = var.dhcp_options_domain_name_servers + ntp_servers = var.dhcp_options_ntp_servers + netbios_name_servers = var.dhcp_options_netbios_name_servers + netbios_node_type = var.dhcp_options_netbios_node_type + ipv6_address_preferred_lease_time = var.dhcp_options_ipv6_address_preferred_lease_time tags = merge( - { "Name" = var.name }, + { "Name" = var.name_prefix }, var.tags, var.dhcp_options_tags, ) @@ -115,7 +116,10 @@ resource "aws_subnet" "public" { { Name = try( var.public_subnet_names[count.index], - format("${var.name}-${var.public_subnet_suffix}-%s", element(var.azs, count.index)) + format("${var.name_prefix}%s-%s-sub-${var.public_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + lookup(var.az_name_to_az_id, element(var.azs, count.index), "") + ) ) }, var.tags, @@ -124,13 +128,22 @@ resource "aws_subnet" "public" { ) } +locals { + num_public_route_tables = var.create_multiple_public_route_tables ? local.len_public_subnets : 1 +} + resource "aws_route_table" "public" { - count = local.create_public_subnets ? 1 : 0 + count = local.create_public_subnets ? local.num_public_route_tables : 0 vpc_id = local.vpc_id tags = merge( - { "Name" = "${var.name}-${var.public_subnet_suffix}" }, + { + "Name" = var.create_multiple_public_route_tables ? format( + "${var.name_prefix}%s-rtb-${var.public_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + ) : "${var.name_prefix}-rtb-${var.public_subnet_suffix}" + }, var.tags, var.public_route_table_tags, ) @@ -140,13 +153,13 @@ resource "aws_route_table_association" "public" { count = local.create_public_subnets ? local.len_public_subnets : 0 subnet_id = element(aws_subnet.public[*].id, count.index) - route_table_id = aws_route_table.public[0].id + route_table_id = element(aws_route_table.public[*].id, var.create_multiple_public_route_tables ? count.index : 0) } resource "aws_route" "public_internet_gateway" { - count = local.create_public_subnets && var.create_igw ? 1 : 0 + count = local.create_public_subnets && var.create_igw ? local.num_public_route_tables : 0 - route_table_id = aws_route_table.public[0].id + route_table_id = aws_route_table.public[count.index].id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.this[0].id @@ -156,9 +169,9 @@ resource "aws_route" "public_internet_gateway" { } resource "aws_route" "public_internet_gateway_ipv6" { - count = local.create_public_subnets && var.create_igw && var.enable_ipv6 ? 1 : 0 + count = local.create_public_subnets && var.create_igw && var.enable_ipv6 ? local.num_public_route_tables : 0 - route_table_id = aws_route_table.public[0].id + route_table_id = aws_route_table.public[count.index].id destination_ipv6_cidr_block = "::/0" gateway_id = aws_internet_gateway.this[0].id } @@ -174,7 +187,7 @@ resource "aws_network_acl" "public" { subnet_ids = aws_subnet.public[*].id tags = merge( - { "Name" = "${var.name}-${var.public_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.public_subnet_suffix}" }, var.tags, var.public_acl_tags, ) @@ -237,11 +250,15 @@ resource "aws_subnet" "private" { private_dns_hostname_type_on_launch = var.private_subnet_private_dns_hostname_type_on_launch vpc_id = local.vpc_id + # app1-test-euc1a-az2-sub-db tags = merge( { Name = try( var.private_subnet_names[count.index], - format("${var.name}-${var.private_subnet_suffix}-%s", element(var.azs, count.index)) + format("${var.name_prefix}%s-%s-sub-${var.private_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + lookup(var.az_name_to_az_id, element(var.azs, count.index), "") + ) ) }, var.tags, @@ -258,9 +275,10 @@ resource "aws_route_table" "private" { tags = merge( { - "Name" = var.single_nat_gateway ? "${var.name}-${var.private_subnet_suffix}" : format( - "${var.name}-${var.private_subnet_suffix}-%s", - element(var.azs, count.index), + "Name" = (var.single_nat_gateway ? "${var.name_prefix}-rtb-${var.private_subnet_suffix}" : + format("${var.name_prefix}%s-rtb-${var.private_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + ) ) }, var.tags, @@ -293,7 +311,7 @@ resource "aws_network_acl" "private" { subnet_ids = aws_subnet.private[*].id tags = merge( - { "Name" = "${var.name}-${var.private_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.private_subnet_suffix}" }, var.tags, var.private_acl_tags, ) @@ -361,7 +379,9 @@ resource "aws_subnet" "database" { { Name = try( var.database_subnet_names[count.index], - format("${var.name}-${var.database_subnet_suffix}-%s", element(var.azs, count.index), ) + format("${var.name_prefix}%s-sub-${var.database_subnet_suffix}", element(var.azs, count.index), + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + ) ) }, var.tags, @@ -372,13 +392,13 @@ resource "aws_subnet" "database" { resource "aws_db_subnet_group" "database" { count = local.create_database_subnets && var.create_database_subnet_group ? 1 : 0 - name = lower(coalesce(var.database_subnet_group_name, var.name)) - description = "Database subnet group for ${var.name}" + name = lower(coalesce(var.database_subnet_group_name, var.name_prefix)) + description = "Database subnet group for ${var.name_prefix}" subnet_ids = aws_subnet.database[*].id tags = merge( { - "Name" = lower(coalesce(var.database_subnet_group_name, var.name)) + "Name" = lower(coalesce(var.database_subnet_group_name, var.name_prefix)) }, var.tags, var.database_subnet_group_tags, @@ -392,9 +412,9 @@ resource "aws_route_table" "database" { tags = merge( { - "Name" = var.single_nat_gateway || var.create_database_internet_gateway_route ? "${var.name}-${var.database_subnet_suffix}" : format( - "${var.name}-${var.database_subnet_suffix}-%s", - element(var.azs, count.index), + "Name" = var.single_nat_gateway || var.create_database_internet_gateway_route ? "${var.name_prefix}-rtb-${var.database_subnet_suffix}" : format( + "${var.name_prefix}%s-rtb-${var.database_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), ) }, var.tags, @@ -475,7 +495,7 @@ resource "aws_network_acl" "database" { subnet_ids = aws_subnet.database[*].id tags = merge( - { "Name" = "${var.name}-${var.database_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.database_subnet_suffix}" }, var.tags, var.database_acl_tags, ) @@ -543,7 +563,9 @@ resource "aws_subnet" "redshift" { { Name = try( var.redshift_subnet_names[count.index], - format("${var.name}-${var.redshift_subnet_suffix}-%s", element(var.azs, count.index)) + format("${var.name_prefix}%s-${var.redshift_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1) + ) ) }, var.tags, @@ -554,12 +576,12 @@ resource "aws_subnet" "redshift" { resource "aws_redshift_subnet_group" "redshift" { count = local.create_redshift_subnets && var.create_redshift_subnet_group ? 1 : 0 - name = lower(coalesce(var.redshift_subnet_group_name, var.name)) - description = "Redshift subnet group for ${var.name}" + name = lower(coalesce(var.redshift_subnet_group_name, var.name_prefix)) + description = "Redshift subnet group for ${var.name_prefix}" subnet_ids = aws_subnet.redshift[*].id tags = merge( - { "Name" = coalesce(var.redshift_subnet_group_name, var.name) }, + { "Name" = coalesce(var.redshift_subnet_group_name, var.name_prefix) }, var.tags, var.redshift_subnet_group_tags, ) @@ -571,7 +593,7 @@ resource "aws_route_table" "redshift" { vpc_id = local.vpc_id tags = merge( - { "Name" = "${var.name}-${var.redshift_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-rtb-${var.redshift_subnet_suffix}" }, var.tags, var.redshift_route_table_tags, ) @@ -612,7 +634,7 @@ resource "aws_network_acl" "redshift" { subnet_ids = aws_subnet.redshift[*].id tags = merge( - { "Name" = "${var.name}-${var.redshift_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.redshift_subnet_suffix}" }, var.tags, var.redshift_acl_tags, ) @@ -680,7 +702,9 @@ resource "aws_subnet" "elasticache" { { Name = try( var.elasticache_subnet_names[count.index], - format("${var.name}-${var.elasticache_subnet_suffix}-%s", element(var.azs, count.index)) + format("${var.name_prefix}%s-${var.elasticache_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1) + ) ) }, var.tags, @@ -691,12 +715,12 @@ resource "aws_subnet" "elasticache" { resource "aws_elasticache_subnet_group" "elasticache" { count = local.create_elasticache_subnets && var.create_elasticache_subnet_group ? 1 : 0 - name = coalesce(var.elasticache_subnet_group_name, var.name) - description = "ElastiCache subnet group for ${var.name}" + name = coalesce(var.elasticache_subnet_group_name, var.name_prefix) + description = "ElastiCache subnet group for ${var.name_prefix}" subnet_ids = aws_subnet.elasticache[*].id tags = merge( - { "Name" = coalesce(var.elasticache_subnet_group_name, var.name) }, + { "Name" = coalesce(var.elasticache_subnet_group_name, var.name_prefix) }, var.tags, var.elasticache_subnet_group_tags, ) @@ -708,7 +732,7 @@ resource "aws_route_table" "elasticache" { vpc_id = local.vpc_id tags = merge( - { "Name" = "${var.name}-${var.elasticache_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-rtb-${var.elasticache_subnet_suffix}" }, var.tags, var.elasticache_route_table_tags, ) @@ -742,7 +766,7 @@ resource "aws_network_acl" "elasticache" { subnet_ids = aws_subnet.elasticache[*].id tags = merge( - { "Name" = "${var.name}-${var.elasticache_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.elasticache_subnet_suffix}" }, var.tags, var.elasticache_acl_tags, ) @@ -809,7 +833,9 @@ resource "aws_subnet" "intra" { { Name = try( var.intra_subnet_names[count.index], - format("${var.name}-${var.intra_subnet_suffix}-%s", element(var.azs, count.index)) + format("${var.name_prefix}%s-sub-${var.intra_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1) + ) ) }, var.tags, @@ -817,13 +843,22 @@ resource "aws_subnet" "intra" { ) } +locals { + num_intra_route_tables = var.create_multiple_intra_route_tables ? local.len_intra_subnets : 1 +} + resource "aws_route_table" "intra" { - count = local.create_intra_subnets ? 1 : 0 + count = local.create_intra_subnets ? local.num_intra_route_tables : 0 vpc_id = local.vpc_id tags = merge( - { "Name" = "${var.name}-${var.intra_subnet_suffix}" }, + { + "Name" = var.create_multiple_intra_route_tables ? format( + "${var.name_prefix}%s-${var.intra_subnet_suffix}-%s", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1), + ) : "${var.name_prefix}-rtb-${var.intra_subnet_suffix}" + }, var.tags, var.intra_route_table_tags, ) @@ -833,7 +868,7 @@ resource "aws_route_table_association" "intra" { count = local.create_intra_subnets ? local.len_intra_subnets : 0 subnet_id = element(aws_subnet.intra[*].id, count.index) - route_table_id = element(aws_route_table.intra[*].id, 0) + route_table_id = element(aws_route_table.intra[*].id, var.create_multiple_intra_route_tables ? count.index : 0) } ################################################################################ @@ -851,7 +886,7 @@ resource "aws_network_acl" "intra" { subnet_ids = aws_subnet.intra[*].id tags = merge( - { "Name" = "${var.name}-${var.intra_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.intra_subnet_suffix}" }, var.tags, var.intra_acl_tags, ) @@ -920,7 +955,7 @@ resource "aws_subnet" "outpost" { { Name = try( var.outpost_subnet_names[count.index], - format("${var.name}-${var.outpost_subnet_suffix}-%s", var.outpost_az) + format("${var.name_prefix}-%s-sub-${var.outpost_subnet_suffix}", var.outpost_az) ) }, var.tags, @@ -953,7 +988,7 @@ resource "aws_network_acl" "outpost" { subnet_ids = aws_subnet.outpost[*].id tags = merge( - { "Name" = "${var.name}-${var.outpost_subnet_suffix}" }, + { "Name" = "${var.name_prefix}-nacl-${var.outpost_subnet_suffix}" }, var.tags, var.outpost_acl_tags, ) @@ -1003,7 +1038,7 @@ resource "aws_internet_gateway" "this" { vpc_id = local.vpc_id tags = merge( - { "Name" = var.name }, + { "Name" = "${var.name_prefix}-igw" }, var.tags, var.igw_tags, ) @@ -1015,14 +1050,14 @@ resource "aws_egress_only_internet_gateway" "this" { vpc_id = local.vpc_id tags = merge( - { "Name" = var.name }, + { "Name" = "${var.name_prefix}-eigw" }, var.tags, var.igw_tags, ) } resource "aws_route" "private_ipv6_egress" { - count = local.create_vpc && var.create_egress_only_igw && var.enable_ipv6 ? local.len_private_subnets : 0 + count = local.create_vpc && var.create_egress_only_igw && var.enable_ipv6 && local.len_private_subnets > 0 ? local.nat_gateway_count : 0 route_table_id = element(aws_route_table.private[*].id, count.index) destination_ipv6_cidr_block = "::/0" @@ -1035,7 +1070,7 @@ resource "aws_route" "private_ipv6_egress" { locals { nat_gateway_count = var.single_nat_gateway ? 1 : var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length - nat_gateway_ips = var.reuse_nat_ips ? var.external_nat_ip_ids : try(aws_eip.nat[*].id, []) + nat_gateway_ips = var.reuse_nat_ips ? var.external_nat_ip_ids : aws_eip.nat[*].id } resource "aws_eip" "nat" { @@ -1046,8 +1081,10 @@ resource "aws_eip" "nat" { tags = merge( { "Name" = format( - "${var.name}-%s", - element(var.azs, var.single_nat_gateway ? 0 : count.index), + "${var.name_prefix}%s-eip", + substr(element(var.azs, var.single_nat_gateway ? 0 : count.index), + length(element(var.azs, var.single_nat_gateway ? 0 : count.index)) - 1, 1 + ) ) }, var.tags, @@ -1072,8 +1109,10 @@ resource "aws_nat_gateway" "this" { tags = merge( { "Name" = format( - "${var.name}-%s", - element(var.azs, var.single_nat_gateway ? 0 : count.index), + "${var.name_prefix}%s-natgw", + substr(element(var.azs, var.single_nat_gateway ? 0 : count.index), + length(element(var.azs, var.single_nat_gateway ? 0 : count.index)) - 1, 1 + ) ) }, var.tags, @@ -1120,10 +1159,14 @@ resource "aws_customer_gateway" "this" { type = "ipsec.1" tags = merge( - { Name = "${var.name}-${each.key}" }, + { Name = "${var.name_prefix}-${each.key}" }, var.tags, var.customer_gateway_tags, ) + + lifecycle { + create_before_destroy = true + } } ################################################################################ @@ -1138,7 +1181,7 @@ resource "aws_vpn_gateway" "this" { availability_zone = var.vpn_gateway_az tags = merge( - { "Name" = var.name }, + { "Name" = "${var.name_prefix}-vpngw" }, var.tags, var.vpn_gateway_tags, ) @@ -1243,7 +1286,7 @@ resource "aws_default_security_group" "this" { } tags = merge( - { "Name" = coalesce(var.default_security_group_name, "${var.name}-default") }, + { "Name" = coalesce(var.default_security_group_name, "${var.name_prefix}-sg-default") }, var.tags, var.default_security_group_tags, ) @@ -1292,7 +1335,7 @@ resource "aws_default_network_acl" "this" { } tags = merge( - { "Name" = coalesce(var.default_network_acl_name, "${var.name}-default") }, + { "Name" = coalesce(var.default_network_acl_name, "${var.name_prefix}-nacl-default") }, var.tags, var.default_network_acl_tags, ) @@ -1337,7 +1380,7 @@ resource "aws_default_route_table" "default" { } tags = merge( - { "Name" = coalesce(var.default_route_table_name, "${var.name}-default") }, + { "Name" = coalesce(var.default_route_table_name, "${var.name_prefix}-rtb-default") }, var.tags, var.default_route_table_tags, ) diff --git a/modules/vpc-endpoints/README.md b/modules/vpc-endpoints/README.md index a59292ae8..0747c4f49 100644 --- a/modules/vpc-endpoints/README.md +++ b/modules/vpc-endpoints/README.md @@ -4,7 +4,7 @@ Terraform sub-module which creates VPC endpoint resources on AWS. ## Usage -See [`examples`](../../examples) directory for working examples to reference: +See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples) directory for working examples to reference: ```hcl module "endpoints" { @@ -48,7 +48,7 @@ module "endpoints" { ## Examples -- [Complete-VPC](../../examples/complete) with VPC Endpoints. +- [Complete-VPC](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/complete) with VPC Endpoints. ## Requirements @@ -56,13 +56,13 @@ module "endpoints" { | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 5.46 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.46 | ## Modules diff --git a/modules/vpc-endpoints/main.tf b/modules/vpc-endpoints/main.tf index 8c4b09c38..5526c3344 100644 --- a/modules/vpc-endpoints/main.tf +++ b/modules/vpc-endpoints/main.tf @@ -24,7 +24,7 @@ resource "aws_vpc_endpoint" "this" { for_each = local.endpoints vpc_id = var.vpc_id - service_name = data.aws_vpc_endpoint_service.this[each.key].service_name + service_name = try(each.value.service_endpoint, data.aws_vpc_endpoint_service.this[each.key].service_name) vpc_endpoint_type = try(each.value.service_type, "Interface") auto_accept = try(each.value.auto_accept, null) @@ -34,6 +34,15 @@ resource "aws_vpc_endpoint" "this" { policy = try(each.value.policy, null) private_dns_enabled = try(each.value.service_type, "Interface") == "Interface" ? try(each.value.private_dns_enabled, null) : null + dynamic "dns_options" { + for_each = try([each.value.dns_options], []) + + content { + dns_record_ip_type = try(dns_options.value.dns_options.dns_record_ip_type, null) + private_dns_only_for_inbound_resolver_endpoint = try(dns_options.value.private_dns_only_for_inbound_resolver_endpoint, null) + } + } + tags = merge(var.tags, try(each.value.tags, {})) timeouts { diff --git a/modules/vpc-endpoints/versions.tf b/modules/vpc-endpoints/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/modules/vpc-endpoints/versions.tf +++ b/modules/vpc-endpoints/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/outputs.tf b/outputs.tf index c8d27e27b..2e59a02cd 100644 --- a/outputs.tf +++ b/outputs.tf @@ -2,6 +2,7 @@ locals { redshift_route_table_ids = aws_route_table.redshift[*].id public_route_table_ids = aws_route_table.public[*].id private_route_table_ids = aws_route_table.private[*].id + tgw_route_table_ids = aws_route_table.tgw[*].id } ################################################################################ @@ -484,6 +485,11 @@ output "natgw_ids" { value = aws_nat_gateway.this[*].id } +output "natgw_interface_ids" { + description = "List of Network Interface IDs assigned to NAT Gateways" + value = aws_nat_gateway.this[*].network_interface_id +} + ################################################################################ # Egress Only Gateway ################################################################################ @@ -604,6 +610,11 @@ output "vpc_flow_log_cloudwatch_iam_role_arn" { value = local.flow_log_iam_role_arn } +output "vpc_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) +} + ################################################################################ # Static values (arguments) ################################################################################ @@ -615,7 +626,7 @@ output "azs" { output "name" { description = "The name of the VPC specified as argument to this module" - value = var.name + value = var.name_prefix } ################################################################################ @@ -650,3 +661,52 @@ output "database_subnets_az_ids" { description = "List of AZ IDs of database subnets" value = aws_subnet.database[*].availability_zone_id } + +################################################################################ +# TGW Subnets +################################################################################ + +output "tgw_subnets" { + description = "List of IDs of tgw subnets" + value = aws_subnet.tgw[*].id +} + +output "tgw_subnet_arns" { + description = "List of ARNs of tgw subnets" + value = aws_subnet.tgw[*].arn +} + +output "tgw_subnets_cidr_blocks" { + description = "List of cidr_blocks of tgw subnets" + value = compact(aws_subnet.tgw[*].cidr_block) +} + +output "tgw_subnets_ipv6_cidr_blocks" { + description = "List of IPv6 cidr_blocks of tgw subnets in an IPv6 enabled VPC" + value = compact(aws_subnet.tgw[*].ipv6_cidr_block) +} + +output "tgw_route_table_ids" { + description = "List of IDs of tgw route tables" + value = local.tgw_route_table_ids +} + +output "tgw_route_table_association_ids" { + description = "List of IDs of the tgw route table association" + value = aws_route_table_association.tgw[*].id +} + +output "tgw_network_acl_id" { + description = "ID of the tgw network ACL" + value = try(aws_network_acl.tgw[0].id, null) +} + +output "tgw_network_acl_arn" { + description = "ARN of the tgw network ACL" + value = try(aws_network_acl.tgw[0].arn, null) +} + +output "aws_ec2_transit_gateway_vpc_attachment_id" { + description = "ID of the TGW attachment" + value = try(aws_ec2_transit_gateway_vpc_attachment.tgw[0].id, null) +} diff --git a/tgw.tf b/tgw.tf new file mode 100644 index 000000000..a2eff7a7e --- /dev/null +++ b/tgw.tf @@ -0,0 +1,218 @@ +################################################################################ +# TGW Subnets +################################################################################ + +locals { + len_tgw_subnets = max(length(var.tgw_subnets), length(var.private_subnet_ipv6_prefixes)) + create_tgw_subnets = local.create_vpc && local.len_tgw_subnets > 0 + + # support variables for transit_gateway_routes + subnets_tgw_routed = keys(var.transit_gateway_routes) +} + +resource "aws_subnet" "tgw" { + count = local.create_tgw_subnets ? local.len_tgw_subnets : 0 + + assign_ipv6_address_on_creation = var.enable_ipv6 && var.tgw_subnet_ipv6_native ? true : var.tgw_subnet_assign_ipv6_address_on_creation + availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null + availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null + cidr_block = var.tgw_subnet_ipv6_native ? null : element(concat(var.tgw_subnets, [""]), count.index) + enable_dns64 = var.enable_ipv6 && var.tgw_subnet_enable_dns64 + enable_resource_name_dns_aaaa_record_on_launch = var.enable_ipv6 && var.tgw_subnet_enable_resource_name_dns_aaaa_record_on_launch + enable_resource_name_dns_a_record_on_launch = !var.tgw_subnet_ipv6_native && var.tgw_subnet_enable_resource_name_dns_a_record_on_launch + ipv6_cidr_block = var.enable_ipv6 && length(var.tgw_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.tgw_subnet_ipv6_prefixes[count.index]) : null + ipv6_native = var.enable_ipv6 && var.tgw_subnet_ipv6_native + private_dns_hostname_type_on_launch = var.tgw_subnet_private_dns_hostname_type_on_launch + vpc_id = local.vpc_id + + #substr(var.input_string, local.string_length - 1, 1) + + tags = merge( + { + Name = try( + var.tgw_subnet_names[count.index], + format("${var.name_prefix}%s-%s-sub-${var.tgw_subnet_suffix}", + substr(element(var.azs, count.index),length(element(var.azs, count.index)) - 1 , 1), + lookup(var.az_name_to_az_id, element(var.azs, count.index), "") + ) + ) + }, + var.tags, + var.tgw_subnet_tags, + lookup(var.tgw_subnet_tags_per_az, element(var.azs, count.index), {}) + ) +} + +# There are as many routing tables as the number of NAT gateways +resource "aws_route_table" "tgw" { + count = local.create_tgw_subnets && local.max_subnet_length > 0 ? local.nat_gateway_count : 0 + + vpc_id = local.vpc_id + + tags = merge( + { + "Name" = var.single_nat_gateway ? "${var.name_prefix}-${var.tgw_subnet_suffix}" : format( + "${var.name_prefix}%s-rtb-${var.tgw_subnet_suffix}", + substr(element(var.azs, count.index), length(element(var.azs, count.index)) - 1, 1) + ) + }, + var.tags, + var.tgw_route_table_tags, + ) +} + +resource "aws_route_table_association" "tgw" { + count = local.create_tgw_subnets ? local.len_tgw_subnets : 0 + + subnet_id = element(aws_subnet.tgw[*].id, count.index) + route_table_id = element( + aws_route_table.tgw[*].id, + var.single_nat_gateway ? 0 : count.index, + ) +} + +################################################################################ +# TGW Network ACLs +################################################################################ + +locals { + tgw_network_acl = local.create_tgw_subnets && var.tgw_dedicated_network_acl +} + +resource "aws_network_acl" "tgw" { + count = local.tgw_network_acl ? 1 : 0 + + vpc_id = local.vpc_id + subnet_ids = aws_subnet.tgw[*].id + + tags = merge( + { "Name" = "${var.name_prefix}-nacl-${var.tgw_subnet_suffix}" }, + var.tags, + var.tgw_acl_tags, + ) +} + +resource "aws_network_acl_rule" "tgw_inbound" { + count = local.tgw_network_acl ? length(var.tgw_inbound_acl_rules) : 0 + + network_acl_id = aws_network_acl.private[0].id + + egress = false + rule_number = var.tgw_inbound_acl_rules[count.index]["rule_number"] + rule_action = var.tgw_inbound_acl_rules[count.index]["rule_action"] + from_port = lookup(var.tgw_inbound_acl_rules[count.index], "from_port", null) + to_port = lookup(var.tgw_inbound_acl_rules[count.index], "to_port", null) + icmp_code = lookup(var.tgw_inbound_acl_rules[count.index], "icmp_code", null) + icmp_type = lookup(var.tgw_inbound_acl_rules[count.index], "icmp_type", null) + protocol = var.tgw_inbound_acl_rules[count.index]["protocol"] + cidr_block = lookup(var.tgw_inbound_acl_rules[count.index], "cidr_block", null) + ipv6_cidr_block = lookup(var.tgw_inbound_acl_rules[count.index], "ipv6_cidr_block", null) +} + +resource "aws_network_acl_rule" "tgw_outbound" { + count = local.tgw_network_acl ? length(var.tgw_outbound_acl_rules) : 0 + + network_acl_id = aws_network_acl.tgw[0].id + + egress = true + rule_number = var.tgw_outbound_acl_rules[count.index]["rule_number"] + rule_action = var.tgw_outbound_acl_rules[count.index]["rule_action"] + from_port = lookup(var.tgw_outbound_acl_rules[count.index], "from_port", null) + to_port = lookup(var.tgw_outbound_acl_rules[count.index], "to_port", null) + icmp_code = lookup(var.tgw_outbound_acl_rules[count.index], "icmp_code", null) + icmp_type = lookup(var.tgw_outbound_acl_rules[count.index], "icmp_type", null) + protocol = var.tgw_outbound_acl_rules[count.index]["protocol"] + cidr_block = lookup(var.tgw_outbound_acl_rules[count.index], "cidr_block", null) + ipv6_cidr_block = lookup(var.tgw_outbound_acl_rules[count.index], "ipv6_cidr_block", null) +} + +# Transit Gateway VPC attachment +resource "aws_ec2_transit_gateway_vpc_attachment" "tgw" { + count = var.enable_tgw_attachment ? 1 : 0 + + subnet_ids = aws_subnet.tgw[*].id + transit_gateway_id = var.transit_gateway_id + vpc_id = local.vpc_id + + tags = merge( + { Name = "${var.name_prefix}-tgw-att" } + ) +} + +resource "aws_route" "tgw_nat_gateway" { + count = local.create_vpc && var.enable_tgw_nat_gateway ? local.nat_gateway_count : 0 + + route_table_id = element(aws_route_table.tgw[*].id, count.index) + destination_cidr_block = var.nat_gateway_destination_cidr_block + nat_gateway_id = element(aws_nat_gateway.this[*].id, count.index) + + timeouts { + create = "5m" + } + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} + +resource "aws_route" "tgw_dns64_nat_gateway" { + count = local.create_vpc && var.enable_tgw_nat_gateway && var.enable_ipv6 && var.tgw_subnet_enable_dns64 ? local.nat_gateway_count : 0 + + route_table_id = element(aws_route_table.tgw[*].id, count.index) + destination_ipv6_cidr_block = "64:ff9b::/96" + nat_gateway_id = element(aws_nat_gateway.this[*].id, count.index) + + timeouts { + create = "5m" + } + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} + +# Route: IPv4 routes from public subnets to the Transit Gateway (if configured in var.transit_gateway_routes) +resource "aws_route" "public_to_tgw" { + count = (local.create_public_subnets && contains(local.subnets_tgw_routed, "public")) ? (var.enable_nat_gateway ? length(var.azs) : 1) : 0 + + destination_cidr_block = can(regex("^pl-", var.transit_gateway_routes["public"])) ? null : var.transit_gateway_routes["public"] + destination_prefix_list_id = can(regex("^pl-", var.transit_gateway_routes["public"])) ? var.transit_gateway_routes["public"] : null + + transit_gateway_id = var.transit_gateway_id + route_table_id = element(aws_route_table.public[*].id, count.index) + + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} + +# Route: IPv4 routes from private subnets to the Transit Gateway (if configured in var.transit_gateway_routes) +resource "aws_route" "private_to_tgw" { + count = (local.create_private_subnets && contains(local.subnets_tgw_routed, "private")) ? length(var.azs) : 0 + + destination_cidr_block = can(regex("^pl-", var.transit_gateway_routes["private"])) ? null : var.transit_gateway_routes["private"] + destination_prefix_list_id = can(regex("^pl-", var.transit_gateway_routes["private"])) ? var.transit_gateway_routes["private"] : null + + transit_gateway_id = var.transit_gateway_id + route_table_id = element(aws_route_table.private[*].id, count.index) + + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} + +# Route: IPv4 routes from intra subnets to the Transit Gateway (if configured in var.transit_gateway_routes) +resource "aws_route" "intra_to_tgw" { + count = (local.create_intra_subnets && contains(local.subnets_tgw_routed, "intra")) ? length(var.azs) : 0 + + destination_cidr_block = can(regex("^pl-", var.transit_gateway_routes["intra"])) ? null : var.transit_gateway_routes["intra"] + destination_prefix_list_id = can(regex("^pl-", var.transit_gateway_routes["intra"])) ? var.transit_gateway_routes["intra"] : null + + transit_gateway_id = var.transit_gateway_id + route_table_id = element(aws_route_table.intra[*].id, count.index) + + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} + +# Route: IPv4 routes from public subnets to the Transit Gateway (if configured in var.transit_gateway_routes) +resource "aws_route" "database_to_tgw" { + count = (local.create_database_subnets && contains(local.subnets_tgw_routed, "database")) ? length(var.azs) : 0 + + destination_cidr_block = can(regex("^pl-", var.transit_gateway_routes["database"])) ? null : var.transit_gateway_routes["database"] + destination_prefix_list_id = can(regex("^pl-", var.transit_gateway_routes["database"])) ? var.transit_gateway_routes["database"] : null + + transit_gateway_id = var.transit_gateway_id + route_table_id = element(aws_route_table.database[*].id, count.index) + + depends_on = [aws_ec2_transit_gateway_vpc_attachment.tgw] +} diff --git a/variables.tf b/variables.tf index 148ce3f19..8e72a4936 100644 --- a/variables.tf +++ b/variables.tf @@ -14,6 +14,18 @@ variable "name" { default = "" } +variable "name_prefix" { + description = "Name to be used on all the resources as identifier" + type = string + default = "" +} + +variable "name_suffix" { + description = "Suffix for more detailed resource description" + type = string + default = "" +} + variable "cidr" { description = "(Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`" type = string @@ -38,6 +50,12 @@ variable "azs" { default = [] } +variable "az_name_to_az_id" { + description = "A map of availability zones names to ids in the account" + type = map(string) + default = {} +} + variable "enable_dns_hostnames" { description = "Should be true to enable DNS hostnames in the VPC" type = bool @@ -156,6 +174,12 @@ variable "dhcp_options_netbios_node_type" { default = "" } +variable "dhcp_options_ipv6_address_preferred_lease_time" { + description = "How frequently, in seconds, a running instance with an IPv6 assigned to it goes through DHCPv6 lease renewal (requires enable_dhcp_options set to true)" + type = number + default = null +} + variable "dhcp_options_tags" { description = "Additional tags for the DHCP option set (requires enable_dhcp_options set to true)" type = map(string) @@ -196,6 +220,12 @@ variable "public_subnet_enable_resource_name_dns_a_record_on_launch" { default = false } +variable "create_multiple_public_route_tables" { + description = "Indicates whether to create a separate route table for each public subnet. Default: `false`" + type = bool + default = false +} + variable "public_subnet_ipv6_prefixes" { description = "Assigns IPv6 public subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding IPv4 subnet list" type = list(string) @@ -914,6 +944,12 @@ variable "intra_subnet_enable_resource_name_dns_a_record_on_launch" { default = false } +variable "create_multiple_intra_route_tables" { + description = "Indicates whether to create a separate route table for each intra subnet. Default: `false`" + type = bool + default = false +} + variable "intra_subnet_ipv6_prefixes" { description = "Assigns IPv6 intra subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding IPv4 subnet list" type = list(string) @@ -1222,6 +1258,12 @@ variable "nat_eip_tags" { default = {} } +variable "enable_tgw_nat_gateway" { + description = "Should be true if you want to provision NAT Gateways for each of your TGW networks" + type = bool + default = false +} + ################################################################################ # Customer Gateways ################################################################################ @@ -1466,12 +1508,37 @@ variable "enable_flow_log" { default = false } +variable "vpc_flow_log_iam_role_name" { + description = "Name to use on the VPC Flow Log IAM role created" + type = string + default = "vpc-flow-log-role" +} + +variable "vpc_flow_log_iam_role_use_name_prefix" { + description = "Determines whether the IAM role name (`vpc_flow_log_iam_role_name_name`) is used as a prefix" + type = bool + default = true +} + + variable "vpc_flow_log_permissions_boundary" { description = "The ARN of the Permissions Boundary for the VPC Flow Log IAM Role" type = string default = null } +variable "vpc_flow_log_iam_policy_name" { + description = "Name of the IAM policy" + type = string + default = "vpc-flow-log-to-cloudwatch" +} + +variable "vpc_flow_log_iam_policy_use_name_prefix" { + description = "Determines whether the name of the IAM policy (`vpc_flow_log_iam_policy_name`) is used as a prefix" + type = bool + default = true +} + 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 or `600` seconds" type = number @@ -1485,7 +1552,7 @@ variable "flow_log_traffic_type" { } variable "flow_log_destination_type" { - description = "Type of flow log destination. Can be s3 or cloud-watch-logs" + description = "Type of flow log destination. Can be s3, kinesis-data-firehose or cloud-watch-logs" type = string default = "cloud-watch-logs" } @@ -1502,6 +1569,12 @@ variable "flow_log_destination_arn" { default = "" } +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 @@ -1572,8 +1645,182 @@ variable "flow_log_cloudwatch_log_group_kms_key_id" { 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 "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 } + +################################################################################ +# Transit Gateway +################################################################################ + +variable "transit_gateway_id" { + type = string + description = "Transit gateway id to attach the VPC to. Required when `transit_gateway` subnet is defined." + default = null +} + +variable "transit_gateway_routes" { + description = <<-EOF + Configuration of route(s) to transit gateway. + For each `public` and/or `private` subnets named in the `subnets` variable, + Optionally create routes from the subnet to transit gateway. Specify the CIDR range or a + prefix-list-id that you want routed to the transit gateway. + Example: + ``` + transit_gateway_routes = { + public = "10.0.0.0/8" + private = "pl-123" + } + ``` +EOF + type = any + default = {} +} + +################################################################################ +# TGW Subnets +################################################################################ + +variable "enable_tgw_attachment" { + description = "Enable Transit Gateway Attachment" + type = bool + default = false +} + +variable "tgw_subnets" { + description = "A list of tgw subnets inside the VPC" + type = list(string) + default = [] +} + +variable "tgw_subnet_assign_ipv6_address_on_creation" { + description = "Specify true to indicate that network interfaces created in the specified subnet should be assigned an IPv6 address. Default is `false`" + type = bool + default = false +} + +variable "tgw_subnet_enable_dns64" { + description = "Indicates whether DNS queries made to the Amazon-provided DNS Resolver in this subnet should return synthetic IPv6 addresses for IPv4-only destinations. Default: `true`" + type = bool + default = true +} + +variable "tgw_subnet_enable_resource_name_dns_aaaa_record_on_launch" { + description = "Indicates whether to respond to DNS queries for instance hostnames with DNS AAAA records. Default: `true`" + type = bool + default = true +} + +variable "tgw_subnet_enable_resource_name_dns_a_record_on_launch" { + description = "Indicates whether to respond to DNS queries for instance hostnames with DNS A records. Default: `false`" + type = bool + default = false +} + +variable "tgw_subnet_ipv6_prefixes" { + description = "Assigns IPv6 tgw subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding IPv4 subnet list" + type = list(string) + default = [] +} + +variable "tgw_subnet_ipv6_native" { + description = "Indicates whether to create an IPv6-only subnet. Default: `false`" + type = bool + default = false +} + +variable "tgw_subnet_private_dns_hostname_type_on_launch" { + description = "The type of hostnames to assign to instances in the subnet at launch. For IPv6-only subnets, an instance DNS name must be based on the instance ID. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name`" + type = string + default = null +} + +variable "tgw_subnet_names" { + description = "Explicit values to use in the Name tag on tgw subnets. If empty, Name tags are generated" + type = list(string) + default = [] +} + +variable "tgw_subnet_suffix" { + description = "Suffix to append to tgw subnets name" + type = string + default = "tgw" +} + +variable "tgw_subnet_tags" { + description = "Additional tags for the tgw subnets" + type = map(string) + default = {} +} + +variable "tgw_subnet_tags_per_az" { + description = "Additional tags for the tgw subnets where the primary key is the AZ" + type = map(map(string)) + default = {} +} + +variable "tgw_route_table_tags" { + description = "Additional tags for the tgw route tables" + type = map(string) + default = {} +} + +################################################################################ +# TGW Network ACLs +################################################################################ + +variable "tgw_dedicated_network_acl" { + description = "Whether to use dedicated network ACL (not default) and custom rules for tgw subnets" + type = bool + default = false +} + +variable "tgw_inbound_acl_rules" { + description = "TGW subnets inbound network ACLs" + type = list(map(string)) + default = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = "0.0.0.0/0" + }, + ] +} + +variable "tgw_outbound_acl_rules" { + description = "TGW subnets outbound network ACLs" + type = list(map(string)) + default = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = "0.0.0.0/0" + }, + ] +} + +variable "tgw_acl_tags" { + description = "Additional tags for the tgw subnets network ACL" + type = map(string) + default = {} +} diff --git a/versions.tf b/versions.tf index ddfcb0e05..e1ed6107f 100644 --- a/versions.tf +++ b/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.46" } } } diff --git a/vpc-flow-logs.tf b/vpc-flow-logs.tf index ac9f25758..7697a9274 100644 --- a/vpc-flow-logs.tf +++ b/vpc-flow-logs.tf @@ -1,3 +1,13 @@ +data "aws_region" "current" { + # Call this API only if create_vpc and enable_flow_log are true + count = var.create_vpc && var.enable_flow_log ? 1 : 0 +} + +data "aws_caller_identity" "current" { + # Call this API only if create_vpc and enable_flow_log are true + count = var.create_vpc && var.enable_flow_log ? 1 : 0 +} + locals { # Only create flow log if user selected to create a VPC as well enable_flow_log = var.create_vpc && var.enable_flow_log @@ -8,6 +18,10 @@ locals { 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.vpc_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 == "" ? local.vpc_id : var.flow_log_cloudwatch_log_group_name_suffix + flow_log_group_arns = [ + for log_group in aws_cloudwatch_log_group.flow_log : + "arn:aws:logs:${data.aws_region.current[0].name}:${data.aws_caller_identity.current[0].account_id}:log-group:${log_group.name}:*" + ] } ################################################################################ @@ -17,13 +31,14 @@ locals { 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 - traffic_type = var.flow_log_traffic_type - vpc_id = local.vpc_id - max_aggregation_interval = var.flow_log_max_aggregation_interval + 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 + vpc_id = local.vpc_id + max_aggregation_interval = var.flow_log_max_aggregation_interval dynamic "destination_options" { for_each = var.flow_log_destination_type == "s3" ? [true] : [] @@ -48,6 +63,8 @@ resource "aws_cloudwatch_log_group" "flow_log" { 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.vpc_flow_log_tags) } @@ -55,7 +72,9 @@ resource "aws_cloudwatch_log_group" "flow_log" { resource "aws_iam_role" "vpc_flow_log_cloudwatch" { count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 - name_prefix = "vpc-flow-log-role-" + name = var.vpc_flow_log_iam_role_use_name_prefix ? null : var.vpc_flow_log_iam_role_name + name_prefix = var.vpc_flow_log_iam_role_use_name_prefix ? "${var.vpc_flow_log_iam_role_name}-" : null + assume_role_policy = data.aws_iam_policy_document.flow_log_cloudwatch_assume_role[0].json permissions_boundary = var.vpc_flow_log_permissions_boundary @@ -89,7 +108,8 @@ resource "aws_iam_role_policy_attachment" "vpc_flow_log_cloudwatch" { resource "aws_iam_policy" "vpc_flow_log_cloudwatch" { count = local.create_flow_log_cloudwatch_iam_role ? 1 : 0 - name_prefix = "vpc-flow-log-to-cloudwatch-" + name = var.vpc_flow_log_iam_policy_use_name_prefix ? null : var.vpc_flow_log_iam_policy_name + name_prefix = var.vpc_flow_log_iam_policy_use_name_prefix ? "${var.vpc_flow_log_iam_policy_name}-" : null policy = data.aws_iam_policy_document.vpc_flow_log_cloudwatch[0].json tags = merge(var.tags, var.vpc_flow_log_tags) } @@ -109,6 +129,6 @@ data "aws_iam_policy_document" "vpc_flow_log_cloudwatch" { "logs:DescribeLogStreams", ] - resources = ["*"] + resources = local.flow_log_group_arns } }