diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..31d7ee2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily + +- package-ecosystem: terraform + directories: + - /modules/nacl + - /modules/nat-gateway + - /modules/route-table + - /modules/security-group + - /modules/subnet-group + - /modules/vpc + schedule: + interval: weekly diff --git a/.github/labeler.yaml b/.github/labeler.yaml index 9fc1fce..bc6b780 100644 --- a/.github/labeler.yaml +++ b/.github/labeler.yaml @@ -1,7 +1,4 @@ # Modules -":floppy_disk: dx-gateway": -- modules/dx-gateway/**/* - ":floppy_disk: nacl": - modules/nacl/**/* @@ -14,23 +11,8 @@ ":floppy_disk: security-group": - modules/security-group/**/* +":floppy_disk: subnet-group": +- modules/subnet-group/**/* + ":floppy_disk: vpc": - modules/vpc/**/* - -":floppy_disk: vpc-endpoint-service": -- modules/vpc-endpoint-service/**/* - -":floppy_disk: vpc-gateway-endpoint": -- modules/vpc-gateway-endpoint/**/* - -":floppy_disk: vpc-interface-endpoint": -- modules/vpc-interface-endpoint/**/* - -":floppy_disk: vpc-peering": -- modules/vpc-peering/**/* - -":floppy_disk: vpc-peering-accepter": -- modules/vpc-peering-accepter/**/* - -":floppy_disk: vpc-peering-requester": -- modules/vpc-peering-requester/**/* diff --git a/.github/labels.yaml b/.github/labels.yaml index 6400449..42055ae 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -40,9 +40,6 @@ name: "size/XL" # Modules -- color: "fbca04" - description: "This issue or pull request is related to dx-gateway module." - name: ":floppy_disk: dx-gateway" - color: "fbca04" description: "This issue or pull request is related to nacl module." name: ":floppy_disk: nacl" @@ -61,21 +58,3 @@ - color: "fbca04" description: "This issue or pull request is related to vpc module." name: ":floppy_disk: vpc" -- color: "fbca04" - description: "This issue or pull request is related to vpc-endpoint-service module." - name: ":floppy_disk: vpc-endpoint-service" -- color: "fbca04" - description: "This issue or pull request is related to vpc-gateway-endpoint module." - name: ":floppy_disk: vpc-gateway-endpoint" -- color: "fbca04" - description: "This issue or pull request is related to vpc-interface-endpoint module." - name: ":floppy_disk: vpc-interface-endpoint" -- color: "fbca04" - description: "This issue or pull request is related to vpc-peering module." - name: ":floppy_disk: vpc-peering" -- color: "fbca04" - description: "This issue or pull request is related to vpc-peering-accepter module." - name: ":floppy_disk: vpc-peering-accepter" -- color: "fbca04" - description: "This issue or pull request is related to vpc-peering-requester module." - name: ":floppy_disk: vpc-peering-requester" diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml deleted file mode 100644 index 5011772..0000000 --- a/.github/workflows/integration.yaml +++ /dev/null @@ -1,101 +0,0 @@ -name: Integration - -on: - push: - branches: - - main - pull_request: {} - -concurrency: - group: integration-${{ github.ref }} - cancel-in-progress: true - -jobs: - changed: - runs-on: ubuntu-latest - - outputs: - terraform_modules_changed: ${{ steps.filter-terraform-modules.outputs.changed }} - terraform_modules_files: ${{ steps.filter-terraform-modules.outputs.files }} - terraform_modules_dirs: ${{ steps.filter-terraform-modules.outputs.dirs }} - yaml_changed: ${{ steps.filter-yaml.outputs.changed }} - yaml_files: ${{ steps.filter-yaml.outputs.files }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Get Changed Files - id: changed-files - uses: dorny/paths-filter@v2 - with: - list-files: json - filters: | - modules: - - 'modules/**' - yaml: - - '**/*.yaml' - - '**/*.yml' - - - name: Filter changed Terraform Modules files to outputs - id: filter-terraform-modules - run: | - dirs=$(echo '${{ steps.changed-files.outputs.modules_files }}' | jq '[.[] | match("modules/[^/]+").string] | unique') - echo ::set-output name=changed::${{ steps.changed-files.outputs.modules }} - echo ::set-output name=files::${{ steps.changed-files.outputs.modules_files }} - echo ::set-output name=dirs::$dirs - - - name: Filter changed YAML files to outputs - id: filter-yaml - run: | - echo ::set-output name=changed::${{ steps.changed-files.outputs.yaml }} - echo ::set-output name=files::${{ steps.changed-files.outputs.yaml_files }} - - - terraform: - needs: - - changed - if: ${{ needs.changed.outputs.terraform_modules_changed != 'false' }} - runs-on: ubuntu-latest - - strategy: - matrix: - path: ${{ fromJson(needs.changed.outputs.terraform_modules_dirs) }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set-up terraform - uses: hashicorp/setup-terraform@v1 - - - name: Terraform fmt - id: terraform-fmt - working-directory: ${{ matrix.path }} - run: terraform fmt -check - continue-on-error: true - - - name: Terraform Validate - id: terraform-validate - working-directory: ${{ matrix.path }} - run: | - terraform init -backend=false - terraform validate -no-color - - - yaml: - needs: - - changed - if: ${{ needs.changed.outputs.yaml_changed != 'false' }} - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Lint YAML Files - id: yaml-lint - run: | - yamllint . diff --git a/.github/workflows/pull-request-labeler.yaml b/.github/workflows/pull-request-labeler.yaml index 9ceef35..d5ac851 100644 --- a/.github/workflows/pull-request-labeler.yaml +++ b/.github/workflows/pull-request-labeler.yaml @@ -9,7 +9,7 @@ jobs: steps: - name: Add Labels for PR - uses: actions/labeler@v3 + uses: actions/labeler@v5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" configuration-path: .github/labeler.yaml diff --git a/.github/workflows/sync-labels.yaml b/.github/workflows/sync-labels.yaml index 210f935..d43aa13 100644 --- a/.github/workflows/sync-labels.yaml +++ b/.github/workflows/sync-labels.yaml @@ -6,6 +6,7 @@ on: - main paths: - .github/labels.yaml + workflow_dispatch: {} jobs: sync-labels: @@ -13,10 +14,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Sync labels - uses: crazy-max/ghaction-github-labeler@v3 + uses: crazy-max/ghaction-github-labeler@v5 with: github-token: ${{ secrets.GITHUB_TOKEN }} yaml-file: .github/labels.yaml diff --git a/.github/workflows/terraform.integration.yaml b/.github/workflows/terraform.integration.yaml new file mode 100644 index 0000000..daca2fa --- /dev/null +++ b/.github/workflows/terraform.integration.yaml @@ -0,0 +1,108 @@ +name: Integration (Terraform) + +on: + push: + branches: + - main + pull_request: {} + +concurrency: + group: terraform-integration-${{ github.ref }} + cancel-in-progress: true + +jobs: + changed: + name: Filter Changed Files and Directories + runs-on: ubuntu-latest + + outputs: + changed: ${{ steps.set-outputs.outputs.changed }} + modified: ${{ steps.set-outputs.outputs.modified }} + changed_files: ${{ steps.set-outputs.outputs.changed_files }} + modified_files: ${{ steps.set-outputs.outputs.modified_files }} + changed_directories: ${{ steps.set-outputs.outputs.changed_directories }} + modified_directories: ${{ steps.set-outputs.outputs.modified_directories }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + modules/** + examples/** + json: true + + - name: Get Changed Directories + id: changed-directories + uses: tj-actions/changed-files@v44 + with: + files: | + modules/** + examples/** + dir_names: "true" + dir_names_max_depth: 2 + json: true + + - name: Set outputs + id: set-outputs + run: | + echo "changed=${{ steps.changed-directories.outputs.any_changed }}" >> $GITHUB_OUTPUT + echo "modified=${{ steps.changed-directories.outputs.any_modified }}" >> $GITHUB_OUTPUT + + echo "changed_files=${{ steps.changed-files.outputs.all_changed_files }}" >> $GITHUB_OUTPUT + echo "modified_files=${{ steps.changed-files.outputs.all_modified_files }}" >> $GITHUB_OUTPUT + + echo "changed_directories=${{ steps.changed-directories.outputs.all_changed_files }}" >> $GITHUB_OUTPUT + echo "modified_directories=${{ steps.changed-directories.outputs.all_modified_files }}" >> $GITHUB_OUTPUT + + + terraform: + name: Lint (terraform) + needs: + - changed + if: ${{ needs.changed.outputs.modified == 'true' }} + uses: tedilabs/.github/.github/workflows/terraform.terraform.yaml@main + + strategy: + matrix: + path: ${{ fromJson(needs.changed.outputs.modified_directories) }} + + with: + terraform_target_dir: ${{ matrix.path }} + terraform_version: latest + terraform_host: app.terraform.io + secrets: + gh_token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} + terraform_token: ${{ secrets.TERRAFORM_TOKEN }} + + + tflint: + name: Lint (tflint) + needs: + - changed + if: ${{ needs.changed.outputs.modified == 'true' }} + uses: tedilabs/.github/.github/workflows/terraform.tflint.yaml@main + + strategy: + matrix: + path: ${{ fromJson(needs.changed.outputs.modified_directories) }} + + with: + tflint_version: latest + tflint_config_file: .tflint.hcl + tflint_target_dir: ${{ matrix.path }} + tflint_recursive_enabled: false + tflint_terraform_init_enabled: true + terraform_version: latest + terraform_host: app.terraform.io + secrets: + gh_token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} + terraform_token: ${{ secrets.TERRAFORM_TOKEN }} diff --git a/.github/workflows/yaml.integration.yaml b/.github/workflows/yaml.integration.yaml new file mode 100644 index 0000000..fc933f2 --- /dev/null +++ b/.github/workflows/yaml.integration.yaml @@ -0,0 +1,60 @@ +name: Integration (YAML) + +on: + push: + branches: + - main + pull_request: {} + +concurrency: + group: yaml-integration-${{ github.ref }} + cancel-in-progress: true + +jobs: + changed: + name: Filter Changed Files and Directories + runs-on: ubuntu-latest + + outputs: + changed: ${{ steps.set-outputs.outputs.changed }} + modified: ${{ steps.set-outputs.outputs.modified }} + changed_files: ${{ steps.set-outputs.outputs.changed_files }} + modified_files: ${{ steps.set-outputs.outputs.modified_files }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + **/*.yaml + **/*.yml + json: true + + - name: Set outputs + id: set-outputs + run: | + echo "changed=${{ steps.changed-files.outputs.any_changed }}" >> $GITHUB_OUTPUT + echo "modified=${{ steps.changed-files.outputs.any_modified }}" >> $GITHUB_OUTPUT + + echo "changed_files=${{ steps.changed-files.outputs.all_changed_files }}" >> $GITHUB_OUTPUT + echo "modified_files=${{ steps.changed-files.outputs.all_modified_files }}" >> $GITHUB_OUTPUT + + lint: + name: Lint (yamllint) + needs: + - changed + if: ${{ needs.changed.outputs.modified == 'true' }} + uses: tedilabs/.github/.github/workflows/yaml.yamllint.yaml@main + + with: + yamllint_version: latest + yamllint_config_file: .yamllint.yaml + yamllint_target_dir: ./ + secrets: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 98ab081..8f8a374 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,25 @@ repos: -- repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.58.0 +- repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.83.4 hooks: - id: terraform_fmt + args: + - --args=-diff - id: terraform_validate + args: + - --tf-init-args=-upgrade + - --hook-config=--retry-once-with-cleanup=true + - id: terraform_providers_lock + args: + - --hook-config=--mode=always-regenerate-lockfile + - id: terraform_tflint + args: + - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl + files: ^modules/ - id: terraform_docs args: ["--args=--sort-by required"] + +- repo: https://github.com/adrienverge/yamllint + rev: v1.32.0 + hooks: + - id: yamllint diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 0000000..0788789 --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,77 @@ +config { + plugin_dir = "~/.tflint.d/plugins" + + format = "compact" + module = true + force = false + disabled_by_default = false + + ignore_module = {} +} + + +################################################### +# Rule Sets - Terraform +################################################### + +plugin "terraform" { + enabled = true + preset = "recommended" +} + +rule "terraform_comment_syntax" { + enabled = true +} + +rule "terraform_documented_variables" { + enabled = true +} + +rule "terraform_documented_outputs" { + enabled = true +} + +rule "terraform_naming_convention" { + enabled = true + format = "snake_case" + + custom_formats = { + extended_snake_case = { + description = "Extended snake_case Format which allows double underscore like `a__b`." + regex = "^[a-z][a-z0-9]+([_]{1,2}[a-z0-9]+)*$" + } + } + + module { + format = "extended_snake_case" + } + + resource { + format = "extended_snake_case" + } + + data { + format = "extended_snake_case" + } +} + +rule "terraform_unused_declarations" { + enabled = false +} + +rule "terraform_unused_required_providers" { + enabled = true +} + + +################################################### +# Rule Sets - AWS +################################################### + +plugin "aws" { + source = "github.com/terraform-linters/tflint-ruleset-aws" + version = "0.21.1" + + enabled = true + deep_check = false +} diff --git a/README.md b/README.md index 83c2d6a..30945e9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,69 @@ ![GitHub](https://img.shields.io/github/license/tedilabs/terraform-aws-network?color=blue&style=flat-square) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square)](https://github.com/pre-commit/pre-commit) -Terraform module which creates VPC related resources on AWS. +Terraform module which creates network related resources on AWS. + +- [nacl](./modules/nacl) +- [nat-gateway](./modules/nat-gateway) +- [route-table](./modules/route-table) +- [security-group](./modules/security-group) +- [subnet-group](./modules/subnet-group) +- [vpc](./modules/vpc) + + +## Target AWS Services + +Terraform Modules from [this package](https://github.com/tedilabs/terraform-aws-network) were written to manage the following AWS Services with Terraform. + +- **AWS VPC (Virtual Private Cloud)** + - VPC + - Default Network ACL + - Default Security Group + - Subnet + - Route Table + - NACL (Network ACL) + - Security Group + - Gateways + - Internet Gateway + - Egress-only Internet Gateway + - NAT Gateway + - VPN Gateway (Virtual Private Gateway) + + +## Examples + +### VPC + +- [vpc-full](./examples/vpc-full) +- [vpc-ipv4-secondary-cidrs](./examples/vpc-ipv4-secondary-cidrs) +- [vpc-ipv6-cidrs](./examples/vpc-ipv6-cidrs) +- [vpc-simple](./examples/vpc-simple) +- [vpc-with-ipam](./examples/vpc-with-ipam) + +### Security Group + +- [security-group-simple](./examples/security-group-simple) +- [security-group-with-ipv4-cidrs](./examples/security-group-with-ipv4-cidrs) + +### NAT Gateway + +- [nat-gateway-public](./examples/nat-gateway-public/) +- [nat-gateway-private](./examples/nat-gateway-private/) +- [nat-gateway-private-secondary-ip-addresses](./examples/nat-gateway-private-secondary-ip-addresses) + + +## Other Terraform Modules from Tedilabs + +Enjoying [terraform-aws-network](https://github.com/tedilabs/terraform-aws-network)? Check out some of our other modules: + +- [AWS Container](https://github.com/tedilabs/terraform-aws-container) - A package of Terraform Modules to manage AWS Container resources. +- [AWS Domain](https://github.com/tedilabs/terraform-aws-domain) - A package of Terraform Modules to manage AWS Domain resources. +- [AWS IPAM](https://github.com/tedilabs/terraform-aws-ipam) - A package of Terraform Modules to manage AWS IPAM related resources (IPAM, Elastic IP, Prefix List). +- [AWS Load Balancer](https://github.com/tedilabs/terraform-aws-load-balancer) - A package of Terraform Modules to manage AWS Load Balancer resources. +- [AWS Security](https://github.com/tedilabs/terraform-aws-security) - A package of Terraform Modules to manage AWS Security resources. +- [AWS VPC Connectivity](https://github.com/tedilabs/terraform-aws-vpc-connectivity) - A package of Terraform Modules to manage AWS VPC Connectivity related resources (VPC Peering, VPC Private Link, VPC Lattice, Client VPN, Site-to-Site VPN, DX). + +Or check out [the full list](https://github.com/search?q=org%3Atedilabs+topic%3Aterraform-module&type=repositories) ## Self Promotion @@ -16,4 +78,4 @@ Like this project? Follow the repository on [GitHub](https://github.com/tedilabs Provided under the terms of the [Apache License](LICENSE). -Copyright © 2021-2022, [Byungjin Park](https://www.posquit0.com). +Copyright © 2021-2023, [Byungjin Park](https://www.posquit0.com). diff --git a/VERSION b/VERSION index 4e8f395..fd9620c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.26.0 +0.32.1 diff --git a/examples/nat-gateway-private-secondary-ip-addresses/main.tf b/examples/nat-gateway-private-secondary-ip-addresses/main.tf new file mode 100644 index 0000000..3a5add1 --- /dev/null +++ b/examples/nat-gateway-private-secondary-ip-addresses/main.tf @@ -0,0 +1,84 @@ +provider "aws" { + region = "us-east-1" +} + +data "aws_vpc" "default" { + default = true +} + +data "aws_subnets" "default" { + filter { + name = "vpc-id" + values = [data.aws_vpc.default.id] + } +} + + +################################################### +# Public NAT Gateway +################################################### + +module "nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-count" + is_private = true + subnet = data.aws_subnets.default.ids[0] + + + ## Primary IP Address + primary_ip_assignment = { + # Automatically assign a public IP address to the NAT Gateway + private_ip = null + } + + + ## Secondary IP Addresses + secondary_ip_count = 7 + + + tags = { + "project" = "terraform-aws-network-examples" + } +} + +module "nat_gateway_2" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-assingments" + is_private = true + subnet = data.aws_subnets.default.ids[0] + + + ## Primary IP Address + primary_ip_assignment = { + # Automatically assign a public IP address to the NAT Gateway + private_ip = "172.31.51.100" + } + + + ## Secondary IP Addresses + secondary_ip_assignments = [ + { + private_ip = "172.31.51.101" + }, + { + private_ip = "172.31.51.102" + }, + { + private_ip = "172.31.51.103" + }, + { + private_ip = "172.31.51.104" + }, + ] + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/nat-gateway-private-secondary-ip-addresses/outputs.tf b/examples/nat-gateway-private-secondary-ip-addresses/outputs.tf new file mode 100644 index 0000000..c0ba79e --- /dev/null +++ b/examples/nat-gateway-private-secondary-ip-addresses/outputs.tf @@ -0,0 +1,7 @@ +output "nat_gateway" { + description = "The NAT Gateways." + value = { + count = module.nat_gateway + assignments = module.nat_gateway_2 + } +} diff --git a/modules/dx-gateway/versions.tf b/examples/nat-gateway-private-secondary-ip-addresses/versions.tf similarity index 61% rename from modules/dx-gateway/versions.tf rename to examples/nat-gateway-private-secondary-ip-addresses/versions.tf index 6078ceb..59c42e8 100644 --- a/modules/dx-gateway/versions.tf +++ b/examples/nat-gateway-private-secondary-ip-addresses/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = "~> 1.5" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = "~> 5.0" } } } diff --git a/examples/nat-gateway-private/main.tf b/examples/nat-gateway-private/main.tf new file mode 100644 index 0000000..0dee5c9 --- /dev/null +++ b/examples/nat-gateway-private/main.tf @@ -0,0 +1,41 @@ +provider "aws" { + region = "us-east-1" +} + +data "aws_vpc" "default" { + default = true +} + +data "aws_subnets" "default" { + filter { + name = "vpc-id" + values = [data.aws_vpc.default.id] + } +} + + +################################################### +# Public NAT Gateway +################################################### + +module "nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test/az1" + is_private = true + subnet = data.aws_subnets.default.ids[0] + + + ## Primary IP Address + primary_ip_assignment = { + # Automatically assign a public IP address to the NAT Gateway + private_ip = null + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/nat-gateway-private/outputs.tf b/examples/nat-gateway-private/outputs.tf new file mode 100644 index 0000000..1e20c3a --- /dev/null +++ b/examples/nat-gateway-private/outputs.tf @@ -0,0 +1,4 @@ +output "nat_gateway" { + description = "The NAT Gateway." + value = module.nat_gateway +} diff --git a/modules/vpc-endpoint-service/versions.tf b/examples/nat-gateway-private/versions.tf similarity index 61% rename from modules/vpc-endpoint-service/versions.tf rename to examples/nat-gateway-private/versions.tf index 6078ceb..59c42e8 100644 --- a/modules/vpc-endpoint-service/versions.tf +++ b/examples/nat-gateway-private/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = "~> 1.5" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = "~> 5.0" } } } diff --git a/examples/nat-gateway-public/main.tf b/examples/nat-gateway-public/main.tf new file mode 100644 index 0000000..5970f38 --- /dev/null +++ b/examples/nat-gateway-public/main.tf @@ -0,0 +1,57 @@ +provider "aws" { + region = "us-east-1" +} + +data "aws_vpc" "default" { + default = true +} + +data "aws_subnets" "default" { + filter { + name = "vpc-id" + values = [data.aws_vpc.default.id] + } +} + + +################################################### +# Elastic IP +################################################### + +module "elastic_ip" { + source = "tedilabs/ipam/aws//modules/elastic-ip" + version = "~> 0.3.0" + + name = "nat-gw-public" + type = "AMAZON" + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# Public NAT Gateway +################################################### + +module "nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test/az1" + is_private = false + subnet = data.aws_subnets.default.ids[0] + + + ## Primary IP Address + primary_ip_assignment = { + elastic_ip = module.elastic_ip.id + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/nat-gateway-public/outputs.tf b/examples/nat-gateway-public/outputs.tf new file mode 100644 index 0000000..57010c1 --- /dev/null +++ b/examples/nat-gateway-public/outputs.tf @@ -0,0 +1,9 @@ +output "elastic_ip" { + description = "The Elastic IP." + value = module.elastic_ip +} + +output "nat_gateway" { + description = "The NAT Gateway." + value = module.nat_gateway +} diff --git a/modules/vpc-gateway-endpoint/versions.tf b/examples/nat-gateway-public/versions.tf similarity index 61% rename from modules/vpc-gateway-endpoint/versions.tf rename to examples/nat-gateway-public/versions.tf index 6078ceb..59c42e8 100644 --- a/modules/vpc-gateway-endpoint/versions.tf +++ b/examples/nat-gateway-public/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = "~> 1.5" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = "~> 5.0" } } } diff --git a/examples/security-group-simple/main.tf b/examples/security-group-simple/main.tf new file mode 100644 index 0000000..b5fd32f --- /dev/null +++ b/examples/security-group-simple/main.tf @@ -0,0 +1,26 @@ +provider "aws" { + region = "us-east-1" +} + +data "aws_vpc" "default" { + default = true +} + + +################################################### +# Security Group +################################################### + +module "security_group" { + source = "../../modules/security-group" + # source = "tedilabs/ipam/aws//modules/security-group" + # version = "~> 0.30.0" + + vpc_id = data.aws_vpc.default.id + + name = "hello-world" + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/security-group-simple/outputs.tf b/examples/security-group-simple/outputs.tf new file mode 100644 index 0000000..ee0168f --- /dev/null +++ b/examples/security-group-simple/outputs.tf @@ -0,0 +1,4 @@ +output "security_group" { + description = "The Security Group." + value = module.security_group +} diff --git a/modules/vpc-interface-endpoint/versions.tf b/examples/security-group-simple/versions.tf similarity index 61% rename from modules/vpc-interface-endpoint/versions.tf rename to examples/security-group-simple/versions.tf index 6078ceb..59c42e8 100644 --- a/modules/vpc-interface-endpoint/versions.tf +++ b/examples/security-group-simple/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = "~> 1.5" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = "~> 5.0" } } } diff --git a/examples/security-group-with-ipv4-cidrs/main.tf b/examples/security-group-with-ipv4-cidrs/main.tf new file mode 100644 index 0000000..9b71880 --- /dev/null +++ b/examples/security-group-with-ipv4-cidrs/main.tf @@ -0,0 +1,50 @@ +provider "aws" { + region = "us-east-1" +} + +data "aws_vpc" "default" { + default = true +} + + +################################################### +# Security Group +################################################### + +module "security_group" { + source = "../../modules/security-group" + # source = "tedilabs/ipam/aws//modules/security-group" + # version = "~> 0.30.0" + + vpc_id = data.aws_vpc.default.id + + name = "hello-world-ipv4-cidrs" + description = "Sample Security Group with IPv4 CIDRs." + + revoke_rules_on_delete = true + + ingress_rules = [ + { + id = "tcp/80" + description = "Allow HTTP from VPC" + from_port = 80 + to_port = 80 + protocol = "tcp" + ipv4_cidrs = ["192.168.0.0/16", "10.0.0.0/8", "172.168.0.0/24"] + }, + ] + egress_rules = [ + { + id = "all/all" + description = "Allow all traffics to the internet" + from_port = 0 + to_port = 0 + protocol = "-1" + ipv4_cidrs = ["0.0.0.0/0"] + }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/security-group-with-ipv4-cidrs/outputs.tf b/examples/security-group-with-ipv4-cidrs/outputs.tf new file mode 100644 index 0000000..ee0168f --- /dev/null +++ b/examples/security-group-with-ipv4-cidrs/outputs.tf @@ -0,0 +1,4 @@ +output "security_group" { + description = "The Security Group." + value = module.security_group +} diff --git a/examples/security-group-with-ipv4-cidrs/versions.tf b/examples/security-group-with-ipv4-cidrs/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/security-group-with-ipv4-cidrs/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/examples/vpc-full/main.tf b/examples/vpc-full/main.tf new file mode 100644 index 0000000..19cc623 --- /dev/null +++ b/examples/vpc-full/main.tf @@ -0,0 +1,101 @@ +provider "aws" { + region = "us-east-1" +} + + +################################################### +# VPC +################################################### + +module "vpc" { + source = "../../modules/vpc" + # source = "tedilabs/network/aws//modules/vpc" + # version = "~> 0.2.0" + + name = "test" + ipv4_cidrs = [ + { + cidr = "10.0.0.0/16" + }, + ] + ipv6_cidrs = [ + { + type = "AMAZON" + }, + ] + + + ## DHCP Option Set + dhcp_options = { + enabled = true + domain_name = "example.com" + domain_name_servers = ["4.4.4.4", "8.8.8.8"] + } + + + ## Gateways + internet_gateway = { + enabled = true + } + egress_only_internet_gateway = { + enabled = true + } + vpn_gateway = { + enabled = true + } + + + ## Defaults + default_network_acl = { + name = "test-default" + ingress_rules = [ + { + priority = 200 + action = "ALLOW" + protocol = "tcp" + from_port = 443 + to_port = 443 + ipv4_cidr = "0.0.0.0/0" + }, + { + priority = 201 + action = "ALLOW" + protocol = "tcp" + from_port = 443 + to_port = 443 + ipv6_cidr = "::/0" + }, + ] + } + default_security_group = { + name = "test-default" + ingress_rules = [ + { + protocol = "tcp" + from_port = 80 + to_port = 80 + ipv4_cidrs = ["10.0.0.0/16"] + }, + { + protocol = "tcp" + from_port = 443 + to_port = 443 + self = true + }, + ] + egress_rules = [ + { + protocol = "all" + from_port = 0 + to_port = 0 + ipv4_cidrs = ["0.0.0.0/0"] + ipv6_cidrs = ["::/0"] + } + ] + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/nacls.tf b/examples/vpc-full/nacls.tf new file mode 100644 index 0000000..4985be0 --- /dev/null +++ b/examples/vpc-full/nacls.tf @@ -0,0 +1,103 @@ +################################################### +# Network ACLs +################################################### + +module "private_network_acl" { + source = "../../modules/nacl" + # source = "tedilabs/network/aws//modules/nacl" + # version = "~> 0.2.0" + + name = "test-private" + vpc_id = module.vpc.id + subnets = module.private_subnet_group.ids + + ingress_rules = { + 900 = { + action = "ALLOW" + protocol = "-1" + ipv4_cidr = "10.0.0.0/16" + } + } + egress_rules = { + 900 = { + action = "ALLOW" + protocol = "-1" + ipv4_cidr = "10.0.0.0/16" + } + } + + tags = { + "project" = "terraform-aws-network-examples" + } +} + +module "public_network_acl" { + source = "../../modules/nacl" + # source = "tedilabs/network/aws//modules/nacl" + # version = "~> 0.2.0" + + name = "test-public" + vpc_id = module.vpc.id + subnets = module.public_subnet_group.ids + + ingress_rules = { + 100 = { + action = "ALLOW" + protocol = "icmp" + ipv4_cidr = "0.0.0.0/0" + icmp_type = -1 + icmp_code = -1 + } + 200 = { + action = "ALLOW" + protocol = "tcp" + ipv4_cidr = "0.0.0.0/0" + from_port = 22 + to_port = 22 + } + 300 = { + action = "ALLOW" + protocol = "tcp" + ipv4_cidr = "0.0.0.0/0" + from_port = 80 + to_port = 80 + } + 310 = { + action = "ALLOW" + protocol = "tcp" + ipv4_cidr = "0.0.0.0/0" + from_port = 443 + to_port = 443 + } + 800 = { + action = "ALLOW" + protocol = "tcp" + ipv4_cidr = "0.0.0.0/0" + from_port = 1024 + to_port = 65535 + } + 801 = { + action = "ALLOW" + protocol = "udp" + ipv4_cidr = "0.0.0.0/0" + from_port = 1024 + to_port = 65535 + } + 900 = { + action = "ALLOW" + protocol = "-1" + ipv4_cidr = "10.0.0.0/16" + } + } + egress_rules = { + 900 = { + action = "ALLOW" + protocol = "-1" + ipv4_cidr = "0.0.0.0/0" + } + } + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/nat-gateways.tf b/examples/vpc-full/nat-gateways.tf new file mode 100644 index 0000000..3df103c --- /dev/null +++ b/examples/vpc-full/nat-gateways.tf @@ -0,0 +1,67 @@ +################################################### +# Elastic IP +################################################### + +module "elastic_ip" { + source = "tedilabs/ipam/aws//modules/elastic-ip" + version = "~> 0.3.0" + + name = "nat-gw-test-public/az2" + type = "AMAZON" + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# Public NAT Gateway +################################################### + +module "public_nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-public/az2" + is_private = false + subnet = module.public_subnet_group.subnets_by_az["use1-az2"][0].id + + + ## Primary IP Address + primary_ip_assignment = { + elastic_ip = module.elastic_ip.id + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# Private NAT Gateway +################################################### + +module "private_nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-private/az2" + is_private = true + subnet = module.private_subnet_group.subnets_by_az["use1-az2"][0].id + + + ## Primary IP Address + primary_ip_assignment = { + private_ip = "10.0.200.7" + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/outputs.tf b/examples/vpc-full/outputs.tf new file mode 100644 index 0000000..22756b4 --- /dev/null +++ b/examples/vpc-full/outputs.tf @@ -0,0 +1,37 @@ +output "vpc" { + description = "The VPC." + value = module.vpc +} + +output "subnet_groups" { + description = "The Subnet Groups for the VPC." + value = { + private = module.private_subnet_group + public = module.public_subnet_group + } +} + +output "nat_gateways" { + description = "The NAT Gateways." + value = { + public = module.public_nat_gateway + private = module.private_nat_gateway + } +} + +output "nacls" { + description = "The Network ACLs." + value = { + public = module.public_network_acl + private = module.private_network_acl + } +} + +output "route_tables" { + description = "The Route Tables." + value = { + public = module.public_route_table + private = module.private_route_table + } +} + diff --git a/examples/vpc-full/route-tables.tf b/examples/vpc-full/route-tables.tf new file mode 100644 index 0000000..625db76 --- /dev/null +++ b/examples/vpc-full/route-tables.tf @@ -0,0 +1,69 @@ +################################################### +# Route Tables +################################################### + +module "private_route_table" { + source = "../../modules/route-table" + # source = "tedilabs/network/aws//modules/route-table" + # version = "~> 0.2.0" + + name = "test-private" + vpc_id = module.vpc.id + subnets = module.private_subnet_group.ids + gateways = [] + + + ## Route Rules + ipv4_routes = [ + { + destination = "0.0.0.0/0" + target = { + type = "NAT_GATEWAY" + id = module.public_nat_gateway.id + } + }, + ] + ipv6_routes = [] + prefix_list_routes = [] + + vpc_gateway_endpoints = [] + propagating_vpn_gateways = [] + + + tags = { + "project" = "terraform-aws-network-examples" + } +} + +module "public_route_table" { + source = "../../modules/route-table" + # source = "tedilabs/network/aws//modules/route-table" + # version = "~> 0.2.0" + + name = "test-public" + vpc_id = module.vpc.id + subnets = module.public_subnet_group.ids + gateways = [] + + + ## Route Rules + ipv4_routes = [ + { + destination = "0.0.0.0/0" + target = { + type = "INTERNET_GATEWAY" + id = module.vpc.internet_gateway.id + } + }, + ] + ipv6_routes = [] + prefix_list_routes = [] + + vpc_gateway_endpoints = [] + propagating_vpn_gateways = [] + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/subnet-groups.tf b/examples/vpc-full/subnet-groups.tf new file mode 100644 index 0000000..d7d21d6 --- /dev/null +++ b/examples/vpc-full/subnet-groups.tf @@ -0,0 +1,147 @@ +################################################### +# Subnet Groups +################################################### + +module "private_subnet_group" { + source = "../../modules/subnet-group" + # source = "tedilabs/network/aws//modules/subnet-group" + # version = "~> 0.2.0" + + name = "test-private" + + vpc_id = module.vpc.id + + subnets = { + "test-private/az2" = { + availability_zone_id = "use1-az2" + ipv4_cidr = "10.0.200.0/24" + } + "test-private/az4" = { + availability_zone_id = "use1-az4" + ipv4_cidr = "10.0.201.0/24" + } + } + + + ## IP Assignments + public_ipv4_address_assignment = { + enabled = false + } + ipv6_address_assignment = { + enabled = false + } + customer_owned_ipv4_address_assignment = { + enabled = false + } + + + ## DNS Configurations + dns_config = { + hostname_type = "RESOURCE_NAME" + dns_resource_name_ipv4_enabled = true + dns_resource_name_ipv6_enabled = false + dns64_enabled = false + } + + ## Integrations + dax_subnet_group = { + enabled = true + name = "test-dax" + description = "Test DAX Subnet Group" + } + dms_replication_subnet_group = { + enabled = true + name = "test-dms-replication" + description = "Test DMS Replication Subnet Group" + } + docdb_subnet_group = { + enabled = true + name = "test-docdb" + description = "Test DocumentDB Subnet Group" + } + elasticache_subnet_group = { + enabled = true + name = "test-elasticache" + description = "Test ElastiCache Subnet Group" + } + memorydb_subnet_group = { + enabled = true + name = "test-memorydb" + description = "Test MemoryDB Subnet Group" + } + neptune_subnet_group = { + enabled = true + name = "test-neptune" + description = "Test Neptune Subnet Group" + } + rds_subnet_group = { + enabled = true + name = "test-rds" + description = "Test RDS Subnet Group" + } + redshift_subnet_group = { + enabled = true + name = "test-redshift" + description = "Test Redshift Subnet Group" + } + + + ## Sharing + shares = [ + # { + # name = "team1" + # principals = ["123456789012"] + # }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } +} + +module "public_subnet_group" { + source = "../../modules/subnet-group" + # source = "tedilabs/network/aws//modules/subnet-group" + # version = "~> 0.2.0" + + name = "test-public" + + vpc_id = module.vpc.id + + subnets = { + "test-public/az2" = { + availability_zone_id = "use1-az2" + ipv4_cidr = "10.0.100.0/24" + } + "test-public/az4" = { + availability_zone_id = "use1-az4" + ipv4_cidr = "10.0.101.0/24" + } + } + + + ## IP Assignments + public_ipv4_address_assignment = { + enabled = true + } + ipv6_address_assignment = { + enabled = false + } + customer_owned_ipv4_address_assignment = { + enabled = false + } + + + ## DNS Configurations + dns_config = { + hostname_type = "RESOURCE_NAME" + dns_resource_name_ipv4_enabled = true + dns_resource_name_ipv6_enabled = false + dns64_enabled = false + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/versions.tf b/examples/vpc-full/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/vpc-full/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/examples/vpc-ipv4-secondary-cidrs/main.tf b/examples/vpc-ipv4-secondary-cidrs/main.tf new file mode 100644 index 0000000..b9d61e8 --- /dev/null +++ b/examples/vpc-ipv4-secondary-cidrs/main.tf @@ -0,0 +1,31 @@ +provider "aws" { + region = "us-east-1" +} + + +################################################### +# VPC +################################################### + +module "vpc" { + source = "../../modules/vpc" + # source = "tedilabs/network/aws//modules/vpc" + # version = "~> 0.2.0" + + name = "test" + ipv4_cidrs = [ + { + cidr = "10.0.0.0/16" + }, + { + cidr = "10.1.0.0/16" + }, + { + cidr = "10.2.0.0/16" + }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-ipv4-secondary-cidrs/outputs.tf b/examples/vpc-ipv4-secondary-cidrs/outputs.tf new file mode 100644 index 0000000..cc46043 --- /dev/null +++ b/examples/vpc-ipv4-secondary-cidrs/outputs.tf @@ -0,0 +1,4 @@ +output "vpc" { + description = "The VPC." + value = module.vpc +} diff --git a/examples/vpc-ipv4-secondary-cidrs/versions.tf b/examples/vpc-ipv4-secondary-cidrs/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/vpc-ipv4-secondary-cidrs/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/examples/vpc-ipv6-cidrs/main.tf b/examples/vpc-ipv6-cidrs/main.tf new file mode 100644 index 0000000..0b5db58 --- /dev/null +++ b/examples/vpc-ipv6-cidrs/main.tf @@ -0,0 +1,30 @@ +provider "aws" { + region = "us-east-1" +} + + +################################################### +# VPC +################################################### + +module "vpc" { + source = "../../modules/vpc" + # source = "tedilabs/network/aws//modules/vpc" + # version = "~> 0.2.0" + + name = "test" + ipv4_cidrs = [ + { + cidr = "10.0.0.0/16" + }, + ] + ipv6_cidrs = [ + { + type = "AMAZON" + }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-ipv6-cidrs/outputs.tf b/examples/vpc-ipv6-cidrs/outputs.tf new file mode 100644 index 0000000..cc46043 --- /dev/null +++ b/examples/vpc-ipv6-cidrs/outputs.tf @@ -0,0 +1,4 @@ +output "vpc" { + description = "The VPC." + value = module.vpc +} diff --git a/examples/vpc-ipv6-cidrs/versions.tf b/examples/vpc-ipv6-cidrs/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/vpc-ipv6-cidrs/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/examples/vpc-simple/main.tf b/examples/vpc-simple/main.tf new file mode 100644 index 0000000..6f94771 --- /dev/null +++ b/examples/vpc-simple/main.tf @@ -0,0 +1,25 @@ +provider "aws" { + region = "us-east-1" +} + + +################################################### +# VPC +################################################### + +module "vpc" { + source = "../../modules/vpc" + # source = "tedilabs/network/aws//modules/vpc" + # version = "~> 0.2.0" + + name = "test" + ipv4_cidrs = [ + { + cidr = "10.0.0.0/16" + }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-simple/outputs.tf b/examples/vpc-simple/outputs.tf new file mode 100644 index 0000000..cc46043 --- /dev/null +++ b/examples/vpc-simple/outputs.tf @@ -0,0 +1,4 @@ +output "vpc" { + description = "The VPC." + value = module.vpc +} diff --git a/examples/vpc-simple/versions.tf b/examples/vpc-simple/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/vpc-simple/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/examples/vpc-with-ipam/ipam.tf b/examples/vpc-with-ipam/ipam.tf new file mode 100644 index 0000000..b19baab --- /dev/null +++ b/examples/vpc-with-ipam/ipam.tf @@ -0,0 +1,55 @@ +data "aws_region" "this" {} + +locals { + region = data.aws_region.this.name +} + + +################################################### +# IPAM +################################################### + +module "ipam" { + source = "tedilabs/ipam/aws//modules/ipam" + version = "~> 0.1.0" + + name = "test" + description = "Managed by Terraform." + + operating_regions = [local.region] + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# IPAM Pools +################################################### + +resource "aws_vpc_ipam_pool" "ipv4" { + address_family = "ipv4" + ipam_scope_id = module.ipam.default_scopes["private"] + locale = local.region +} + +resource "aws_vpc_ipam_pool_cidr" "ipv4" { + ipam_pool_id = aws_vpc_ipam_pool.ipv4.id + cidr = "10.20.0.0/16" + +} + +resource "aws_vpc_ipam_pool" "ipv6" { + address_family = "ipv6" + ipam_scope_id = module.ipam.default_scopes["public"] + locale = local.region + publicly_advertisable = false + public_ip_source = "amazon" + aws_service = "ec2" +} + +resource "aws_vpc_ipam_pool_cidr" "ipv6" { + ipam_pool_id = aws_vpc_ipam_pool.ipv6.id + netmask_length = 52 +} diff --git a/examples/vpc-with-ipam/main.tf b/examples/vpc-with-ipam/main.tf new file mode 100644 index 0000000..a29e791 --- /dev/null +++ b/examples/vpc-with-ipam/main.tf @@ -0,0 +1,63 @@ +provider "aws" { + region = "us-east-1" +} + + +################################################### +# VPC +################################################### + +module "vpc" { + source = "../../modules/vpc" + # source = "tedilabs/network/aws//modules/vpc" + # version = "~> 0.2.0" + + name = "test" + ipv4_cidrs = [ + { + type = "IPAM_POOL" + ipam_pool = { + id = aws_vpc_ipam_pool.ipv4.id + netmask_length = 28 + } + }, + { + cidr = "10.0.0.0/16" + }, + { + type = "IPAM_POOL" + ipam_pool = { + id = aws_vpc_ipam_pool.ipv4.id + netmask_length = 28 + } + }, + ] + ipv6_cidrs = [ + { + type = "AMAZON" + }, + { + type = "IPAM_POOL" + ipam_pool = { + id = aws_vpc_ipam_pool.ipv6.id + netmask_length = 56 + } + }, + { + type = "IPAM_POOL" + ipam_pool = { + id = aws_vpc_ipam_pool.ipv6.id + cidr = "2600:1f28:7f:4100::/56" + } + }, + ] + + tags = { + "project" = "terraform-aws-network-examples" + } + + depends_on = [ + aws_vpc_ipam_pool_cidr.ipv4, + aws_vpc_ipam_pool_cidr.ipv6, + ] +} diff --git a/examples/vpc-with-ipam/outputs.tf b/examples/vpc-with-ipam/outputs.tf new file mode 100644 index 0000000..cc46043 --- /dev/null +++ b/examples/vpc-with-ipam/outputs.tf @@ -0,0 +1,4 @@ +output "vpc" { + description = "The VPC." + value = module.vpc +} diff --git a/examples/vpc-with-ipam/versions.tf b/examples/vpc-with-ipam/versions.tf new file mode 100644 index 0000000..59c42e8 --- /dev/null +++ b/examples/vpc-with-ipam/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/modules/dx-gateway/README.md b/modules/dx-gateway/README.md deleted file mode 100644 index f6d2954..0000000 --- a/modules/dx-gateway/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# dx-gateway - -This module creates following resources. - -- `aws_dx_gateway` -- `aws_dx_gateway_association` (optional) - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.49.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_dx_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dx_gateway) | resource | -| [aws_dx_gateway_association.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dx_gateway_association) | resource | -| [aws_dx_gateway_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dx_gateway_association) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [asn](#input\_asn) | The ASN to be configured on the Amazon side of the connection. The ASN must be in the private range of 64,512 to 65,534 or 4,200,000,000 to 4,294,967,294. | `number` | n/a | yes | -| [name](#input\_name) | Desired name for the DX Gateway resources. | `string` | n/a | yes | -| [cross\_account\_gateway\_associations](#input\_cross\_account\_gateway\_associations) | The configurations to associate VPN Gateway or Transit Gateway with a Direct Connect Gateway in cross account. | `list(any)` | `[]` | no | -| [gateway\_associations](#input\_gateway\_associations) | The configurations to associate VPN Gateway or Transit Gateway with a Direct Connect Gateway in same account. | `list(any)` | `[]` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [asn](#output\_asn) | The ASN of the Amazon side of the connection. | -| [cross\_account\_gateway\_associations](#output\_cross\_account\_gateway\_associations) | Associated VGW or Transit gateway with a Direct Connect Gateway in cross account. | -| [gateway\_associations](#output\_gateway\_associations) | Associated VGW or Transit gateway with a Direct Connect Gateway in same account. | -| [id](#output\_id) | The ID of the DX Gateway. | -| [name](#output\_name) | The name of the DX Gateway. | -| [owner\_account\_id](#output\_owner\_account\_id) | AWS Account ID of the gateway. | - diff --git a/modules/dx-gateway/main.tf b/modules/dx-gateway/main.tf deleted file mode 100644 index 04c6454..0000000 --- a/modules/dx-gateway/main.tf +++ /dev/null @@ -1,38 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } -} - -resource "aws_dx_gateway" "this" { - name = local.metadata.name - amazon_side_asn = var.asn -} - -resource "aws_dx_gateway_association" "this" { - for_each = { - for association in var.gateway_associations : - association.gateway_id => association - } - - dx_gateway_id = aws_dx_gateway.this.id - - associated_gateway_id = each.key - allowed_prefixes = try(each.value.allowed_prefixes, null) -} - -resource "aws_dx_gateway_association" "external" { - for_each = { - for association in var.cross_account_gateway_associations : - association.gateway_id => association - } - - dx_gateway_id = aws_dx_gateway.this.id - - associated_gateway_owner_account_id = each.value.account_id - proposal_id = each.value.proposal_id - allowed_prefixes = try(each.value.allowed_prefixes, null) -} diff --git a/modules/dx-gateway/outputs.tf b/modules/dx-gateway/outputs.tf deleted file mode 100644 index d8d8916..0000000 --- a/modules/dx-gateway/outputs.tf +++ /dev/null @@ -1,29 +0,0 @@ -output "id" { - description = "The ID of the DX Gateway." - value = aws_dx_gateway.this.id -} - -output "name" { - description = "The name of the DX Gateway." - value = aws_dx_gateway.this.name -} - -output "asn" { - description = "The ASN of the Amazon side of the connection." - value = aws_dx_gateway.this.amazon_side_asn -} - -output "owner_account_id" { - description = "AWS Account ID of the gateway." - value = aws_dx_gateway.this.owner_account_id -} - -output "gateway_associations" { - description = "Associated VGW or Transit gateway with a Direct Connect Gateway in same account." - value = aws_dx_gateway_association.this -} - -output "cross_account_gateway_associations" { - description = "Associated VGW or Transit gateway with a Direct Connect Gateway in cross account." - value = aws_dx_gateway_association.external -} diff --git a/modules/dx-gateway/variables.tf b/modules/dx-gateway/variables.tf deleted file mode 100644 index 5d3d6df..0000000 --- a/modules/dx-gateway/variables.tf +++ /dev/null @@ -1,21 +0,0 @@ -variable "name" { - description = "Desired name for the DX Gateway resources." - type = string -} - -variable "asn" { - description = "The ASN to be configured on the Amazon side of the connection. The ASN must be in the private range of 64,512 to 65,534 or 4,200,000,000 to 4,294,967,294." - type = number -} - -variable "gateway_associations" { - description = "The configurations to associate VPN Gateway or Transit Gateway with a Direct Connect Gateway in same account." - type = list(any) - default = [] -} - -variable "cross_account_gateway_associations" { - description = "The configurations to associate VPN Gateway or Transit Gateway with a Direct Connect Gateway in cross account." - type = list(any) - default = [] -} diff --git a/modules/nacl/README.md b/modules/nacl/README.md index 35fcf9c..4afaf0f 100644 --- a/modules/nacl/README.md +++ b/modules/nacl/README.md @@ -3,6 +3,7 @@ This module creates following resources. - `aws_network_acl` +- `aws_network_acl_association` (optional) - `aws_network_acl_rule` (optional) @@ -10,18 +11,20 @@ This module creates following resources. | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 4.59 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 3.45.0 | +| [aws](#provider\_aws) | 5.22.0 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | ## Resources @@ -30,29 +33,30 @@ No modules. | [aws_network_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource | | [aws_network_acl_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl_rule) | resource | | [aws_network_acl_rule.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl_rule) | resource | -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the network ACL resources. | `string` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | The ID of the associated VPC. | `string` | n/a | yes | -| [egress\_rules](#input\_egress\_rules) | A map of egress rules in a network ACL. Use the key of map as the rule number. | `map(map(any))` | `{}` | no | -| [ingress\_rules](#input\_ingress\_rules) | A map of ingress rules in a network ACL. Use the key of map as the rule number. | `map(map(any))` | `{}` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [subnets](#input\_subnets) | A list of subnet IDs to apply the ACL to. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [name](#input\_name) | (Required) Desired name for the network ACL resources. | `string` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC to associate. | `string` | n/a | yes | +| [egress\_rules](#input\_egress\_rules) | (Optional) A set of egress rules in the default Network ACL. Use the key of map as the rule number (priority). If not explicitly defined, the AWS default rules are applied. Each block of `egress_rules` as defined below.
(Required) `priority` - The rule priority. The rule number. Used for ordering.
(Required) `action` - The action to indicate whether to allow or deny the traffic that matches the rule. Valid values are `ALLOW` and `DENY`.
(Required) `protocol` - The protocol to match. If using the `-1` 'all' protocol, you must specify a from and to port of `0`.
(Optional) `from_port` - The from port to match.
(Optional) `to_port` - The to port to match.
(Optional) `ipv4_cidr` - The IPv4 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv6_cidr`.
(Optional) `ipv6_cidr` - The IPv6 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv4_cidr`.
(Optional) `icmp_type` - The ICMP type to be used. Defaults to `0`.
(Optional) `icmp_code` - The ICMP code to be used. Defaults to `0`. |
map(object({
action = string
protocol = string
from_port = optional(number)
to_port = optional(number)
ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
icmp_type = optional(number, 0)
icmp_code = optional(number, 0)
}))
| `{}` | no | +| [ingress\_rules](#input\_ingress\_rules) | (Optional) A map of ingress rules in the default Network ACL. Use the key of map as the rule number (priority). If not explicitly defined, the AWS default rules are applied. Each block of `ingress_rules` as defined below.
(Required) `priority` - The rule priority. The rule number. Used for ordering.
(Required) `action` - The action to indicate whether to allow or deny the traffic that matches the rule. Valid values are `ALLOW` and `DENY`.
(Required) `protocol` - The protocol to match. If using the `-1` `all` protocol, you must specify a from and to port of `0`.
(Optional) `from_port` - The from port to match.
(Optional) `to_port` - The to port to match.
(Optional) `ipv4_cidr` - The IPv4 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv6_cidr`.
(Optional) `ipv6_cidr` - The IPv6 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv4_cidr`.
(Optional) `icmp_type` - The ICMP type to be used. Defaults to `0`.
(Optional) `icmp_code` - The ICMP code to be used. Defaults to `0`. |
map(object({
action = string
protocol = string
from_port = optional(number)
to_port = optional(number)
ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
icmp_type = optional(number, 0)
icmp_code = optional(number, 0)
}))
| `{}` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [subnets](#input\_subnets) | (Optional) A list of subnet IDs to apply the ACL to. | `list(string)` | `[]` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | ## Outputs | Name | Description | |------|-------------| | [arn](#output\_arn) | The ARN of the network ACL. | -| [associated\_subnets](#output\_associated\_subnets) | A list of subnet IDs which is associated with the network ACL. | | [id](#output\_id) | The ID of the network ACL. | +| [name](#output\_name) | The name of the network ACL. | | [owner\_id](#output\_owner\_id) | The ID of the AWS account that owns the network ACL. | +| [subnets](#output\_subnets) | A list of subnet IDs which is associated with the network ACL. | +| [vpc\_id](#output\_vpc\_id) | The VPC ID of the network ACL. | diff --git a/modules/nacl/main.tf b/modules/nacl/main.tf index 98f3660..aaa9084 100644 --- a/modules/nacl/main.tf +++ b/modules/nacl/main.tf @@ -14,6 +14,14 @@ locals { } : {} } + +################################################### +# Network ACL +################################################### + +# INFO: Not supported attributes +# - `ingress` +# - `egress` resource "aws_network_acl" "this" { vpc_id = var.vpc_id subnet_ids = var.subnets @@ -28,6 +36,18 @@ resource "aws_network_acl" "this" { } +################################################### +# Subnet Associations of Network ACL +################################################### + +# resource "aws_network_acl_association" "this" { +# for_each = toset(var.subnets) +# +# network_acl_id = aws_network_acl.this.id +# subnet_id = each.value +# } + + ################################################### # Network ACL Rules ################################################### @@ -37,16 +57,17 @@ resource "aws_network_acl_rule" "ingress" { network_acl_id = aws_network_acl.this.id - egress = false - rule_number = each.key - rule_action = lookup(each.value, "action", "") - protocol = lookup(each.value, "protocol", -1) - from_port = lookup(each.value, "from_port", null) - to_port = lookup(each.value, "to_port", null) - icmp_type = lookup(each.value, "icmp_type", null) - icmp_code = lookup(each.value, "icmp_code", null) - cidr_block = lookup(each.value, "cidr_block", null) - ipv6_cidr_block = lookup(each.value, "ipv6_cidr_block", null) + egress = false + rule_number = each.key + + rule_action = lower(each.value.action) + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + icmp_type = each.value.icmp_type + icmp_code = each.value.icmp_code + cidr_block = each.value.ipv4_cidr + ipv6_cidr_block = each.value.ipv6_cidr } resource "aws_network_acl_rule" "egress" { @@ -54,14 +75,15 @@ resource "aws_network_acl_rule" "egress" { network_acl_id = aws_network_acl.this.id - egress = true - rule_number = each.key - rule_action = lookup(each.value, "action", "") - protocol = lookup(each.value, "protocol", -1) - from_port = lookup(each.value, "from_port", null) - to_port = lookup(each.value, "to_port", null) - icmp_type = lookup(each.value, "icmp_type", null) - icmp_code = lookup(each.value, "icmp_code", null) - cidr_block = lookup(each.value, "cidr_block", null) - ipv6_cidr_block = lookup(each.value, "ipv6_cidr_block", null) + egress = true + rule_number = each.key + + rule_action = lower(each.value.action) + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + icmp_type = each.value.icmp_type + icmp_code = each.value.icmp_code + cidr_block = each.value.ipv4_cidr + ipv6_cidr_block = each.value.ipv6_cidr } diff --git a/modules/nacl/migrations.tf b/modules/nacl/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/nacl/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/nacl/outputs.tf b/modules/nacl/outputs.tf index 70d3515..37cbaec 100644 --- a/modules/nacl/outputs.tf +++ b/modules/nacl/outputs.tf @@ -13,7 +13,17 @@ output "owner_id" { value = aws_network_acl.this.owner_id } -output "associated_subnets" { +output "name" { + description = "The name of the network ACL." + value = var.name +} + +output "vpc_id" { + description = "The VPC ID of the network ACL." + value = aws_network_acl.this.vpc_id +} + +output "subnets" { description = "A list of subnet IDs which is associated with the network ACL." - value = var.subnets + value = aws_network_acl.this.subnet_ids } diff --git a/modules/nacl/resource-group.tf b/modules/nacl/resource-group.tf index af108f9..7487ba0 100644 --- a/modules/nacl/resource-group.tf +++ b/modules/nacl/resource-group.tf @@ -7,37 +7,24 @@ locals { replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), ]) ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON } -resource "aws_resourcegroups_group" "this" { + +module "resource_group" { + source = "tedilabs/misc/aws//modules/resource-group" + version = "~> 0.10.0" + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 name = local.resource_group_name description = var.resource_group_description - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query + query = { + resource_tags = local.module_tags } + module_tags_enabled = false tags = merge( - { - "Name" = local.resource_group_name - }, local.module_tags, var.tags, ) diff --git a/modules/nacl/variables.tf b/modules/nacl/variables.tf index de858af..9b6dcaf 100644 --- a/modules/nacl/variables.tf +++ b/modules/nacl/variables.tf @@ -1,41 +1,104 @@ variable "name" { - description = "Desired name for the network ACL resources." + description = "(Required) Desired name for the network ACL resources." type = string + nullable = false } variable "vpc_id" { - description = "The ID of the associated VPC." + description = "(Required) The ID of the VPC to associate." type = string + nullable = false } variable "subnets" { - description = "A list of subnet IDs to apply the ACL to." + description = "(Optional) A list of subnet IDs to apply the ACL to." type = list(string) default = [] + nullable = false } variable "ingress_rules" { - description = "A map of ingress rules in a network ACL. Use the key of map as the rule number." - type = map(map(any)) - default = {} + description = < [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 5.10 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 3.45.0 | +| [aws](#provider\_aws) | 5.22.0 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | ## Resources | Name | Type | |------|------| -| [aws_eip.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | | [aws_nat_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource | -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | +| [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the NAT Gateway resources. | `string` | n/a | yes | -| [subnet\_id](#input\_subnet\_id) | The ID of the subnet which the NAT Gateway belongs to. | `string` | n/a | yes | -| [assign\_eip\_on\_create](#input\_assign\_eip\_on\_create) | Assign a new Elastic IP to NAT Gateway on create. Set false if you want to provide existing Elastic IP. | `bool` | `false` | no | -| [eip\_id](#input\_eip\_id) | The Allocation ID of the Elastic IP address for the gateway. Create a new Elastic IP if not provided. | `string` | `""` | no | -| [is\_private](#input\_is\_private) | Whether to create the gateway as private or public connectivity type. Defaults to public(false). | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [name](#input\_name) | (Required) Desired name for the NAT Gateway resources. | `string` | n/a | yes | +| [subnet](#input\_subnet) | (Required) The Subnet ID of the subnet in which to place the NAT Gateway. | `string` | n/a | yes | +| [is\_private](#input\_is\_private) | (Optional) Whether to create the NAT gateway as private or public connectivity type. Defaults to `false` (public). | `bool` | `false` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [primary\_ip\_assignment](#input\_primary\_ip\_assignment) | (Optional) A configuration to assign primary ip address with the NAT Gateway. `primary_ip_assignment` as defined below.
(Optional) `elastic_ip` - The allocation ID of Elastic IP address to associate with the NAT Gateway.
(Optional) `private_ip` - The private IP address to associate with the NAT Gateway. If you dont't provide an address, a private IPv4 address will be automatically assigned. |
object({
elastic_ip = optional(string)
private_ip = optional(string)
})
| `{}` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [secondary\_ip\_assignments](#input\_secondary\_ip\_assignments) | (Optional) A configuration to assign secondary ip addresses with the NAT Gateway. Each block of `secondary_ip_assignments` as defined below.
(Optional) `elastic_ip` - The allocation ID of Elastic IP address to associate with the NAT Gateway.
(Optional) `private_ip` - The private IP address to associate with the NAT Gateway. If you dont't provide an address, a private IPv4 address will be automatically assigned. |
list(object({
elastic_ip = optional(string)
private_ip = optional(string)
}))
| `[]` | no | +| [secondary\_ip\_count](#input\_secondary\_ip\_count) | (Optional) The number of secondary private IPv4 addresses to assign to the NAT Gateway. Only used with private NAT Gateway. | `number` | `null` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | (Optional) How long to wait for the NAT Gateway to be created/updated/deleted. |
object({
create = optional(string, "10m")
update = optional(string, "10m")
delete = optional(string, "30m")
})
| `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [connectivity\_type](#output\_connectivity\_type) | Connectivity type for the gateway. Valid values are private and public. | -| [eip\_id](#output\_eip\_id) | The Allocation ID of the Elastic IP address for the gateway. | -| [eni\_id](#output\_eni\_id) | The ENI ID of the network interface created by the NAT gateway. | +| [availability\_zone](#output\_availability\_zone) | The availability zone of the NAT Gateway.
`id` - The ID of the availability zone.
`name` - The name of the availability zone. | +| [elastic\_ip](#output\_elastic\_ip) | The Allocation ID of the Elastic IP address for the gateway. | | [id](#output\_id) | The ID of the NAT Gateway. | -| [private\_ip](#output\_private\_ip) | The private IP address of the NAT Gateway. | -| [public\_ip](#output\_public\_ip) | The public IP address of the NAT Gateway. | +| [is\_private](#output\_is\_private) | Whether the NAT Gateway supports public or private connectivity. | +| [name](#output\_name) | The name of the NAT Gateway. | +| [netework\_interface](#output\_netework\_interface) | The ENI ID of the network interface created by the NAT gateway. | +| [primary\_private\_ip](#output\_primary\_private\_ip) | The private IP address of the NAT Gateway. | +| [primary\_public\_ip](#output\_primary\_public\_ip) | The public IP address of the NAT Gateway. | +| [secondary\_private\_ips](#output\_secondary\_private\_ips) | The secondary private IP addresses of the NAT Gateway. | +| [subnet](#output\_subnet) | The subnet which the NAT Gateway belongs to.
`id` - The ID of the subnet.
`arn` - The ARN of the subnet. | +| [vpc\_id](#output\_vpc\_id) | The VPC ID of the NAT Gateway. | diff --git a/modules/nat-gateway/main.tf b/modules/nat-gateway/main.tf index 9e9756a..6c1b144 100644 --- a/modules/nat-gateway/main.tf +++ b/modules/nat-gateway/main.tf @@ -14,24 +14,47 @@ locals { } : {} } -resource "aws_eip" "this" { - count = !var.is_private && var.assign_eip_on_create ? 1 : 0 +data "aws_subnet" "this" { + id = var.subnet +} - vpc = true - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} +################################################### +# NAT Gateway +################################################### resource "aws_nat_gateway" "this" { connectivity_type = var.is_private ? "private" : "public" - subnet_id = var.subnet_id - allocation_id = length(aws_eip.this) > 0 ? aws_eip.this[0].id : var.eip_id + subnet_id = var.subnet + + + ## Primary IP Addresse + allocation_id = var.primary_ip_assignment.elastic_ip + private_ip = var.primary_ip_assignment.private_ip + + + ## Secondary IP Addresses + secondary_allocation_ids = (!var.is_private + ? [ + for assignment in var.secondary_ip_assignments : + assignment.elastic_ip + ] + : null + ) + secondary_private_ip_addresses = (var.secondary_ip_count == null + ? [ + for assignment in var.secondary_ip_assignments : + assignment.private_ip + ] + : null + ) + secondary_private_ip_address_count = var.secondary_ip_count + + timeouts { + create = var.timeouts.create + update = var.timeouts.update + delete = var.timeouts.delete + } tags = merge( { @@ -40,4 +63,14 @@ resource "aws_nat_gateway" "this" { local.module_tags, var.tags, ) + + lifecycle { + precondition { + condition = anytrue([ + var.secondary_ip_count == null, + var.secondary_ip_count != null && var.is_private == true, + ]) + error_message = "`secondary_ip_count` variable is only supported with private NAT Gateway." + } + } } diff --git a/modules/nat-gateway/migrations.tf b/modules/nat-gateway/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/nat-gateway/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/nat-gateway/outputs.tf b/modules/nat-gateway/outputs.tf index 2891a6b..eb4cf21 100644 --- a/modules/nat-gateway/outputs.tf +++ b/modules/nat-gateway/outputs.tf @@ -3,27 +3,66 @@ output "id" { value = aws_nat_gateway.this.id } -output "connectivity_type" { - description = "Connectivity type for the gateway. Valid values are private and public." - value = aws_nat_gateway.this.connectivity_type +output "name" { + description = "The name of the NAT Gateway." + value = var.name } -output "eip_id" { +output "is_private" { + description = "Whether the NAT Gateway supports public or private connectivity." + value = aws_nat_gateway.this.connectivity_type == "private" +} + +output "availability_zone" { + description = < 0 && var.secondary_ip_count < 32 + : true + ) + error_message = "`secondary_ip_count` must be greater than 0 and less than 32." + } +} + +variable "timeouts" { + description = "(Optional) How long to wait for the NAT Gateway to be created/updated/deleted." + type = object({ + create = optional(string, "10m") + update = optional(string, "10m") + delete = optional(string, "30m") + }) + default = {} + nullable = false } variable "tags" { - description = "A map of tags to add to all resources." + description = "(Optional) A map of tags to add to all resources." type = map(string) default = {} + nullable = false } variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." + description = "(Optional) Whether to create AWS Resource Tags for the module informations." type = bool default = true + nullable = false } @@ -44,19 +102,22 @@ variable "module_tags_enabled" { ################################################### variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." + description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." type = bool default = true + nullable = false } variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." + description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." type = string default = "" + nullable = false } variable "resource_group_description" { - description = "The description of Resource Group." + description = "(Optional) The description of Resource Group." type = string default = "Managed by Terraform." + nullable = false } diff --git a/modules/nat-gateway/versions.tf b/modules/nat-gateway/versions.tf index 6078ceb..c46e4aa 100644 --- a/modules/nat-gateway/versions.tf +++ b/modules/nat-gateway/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = ">= 1.6" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = ">= 5.10" } } } diff --git a/modules/route-table/README.md b/modules/route-table/README.md index 6e94ff1..a6b7eb4 100644 --- a/modules/route-table/README.md +++ b/modules/route-table/README.md @@ -14,25 +14,26 @@ This module creates following resources. | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 5.11 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 3.45.0 | +| [aws](#provider\_aws) | 5.23.1 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | ## Resources | Name | Type | |------|------| | [aws_main_route_table_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/main_route_table_association) | resource | -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | | [aws_route.ipv4](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | | [aws_route.ipv6](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | | [aws_route.prefix_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | @@ -46,31 +47,37 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the route table resources. | `string` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | The ID of the VPC which the route table belongs to. | `string` | n/a | yes | -| [gateways](#input\_gateways) | A list of gateway IDs to associate with the route table. Only support Internet Gateway and Virtual Private Gateway. | `list(string)` | `[]` | no | -| [ipv4\_routes](#input\_ipv4\_routes) | A list of route rules for IPv4 CIDRs. | `list(map(string))` | `[]` | no | -| [ipv6\_routes](#input\_ipv6\_routes) | A list of route rules for IPv6 CIDRs. | `list(map(string))` | `[]` | no | -| [is\_main](#input\_is\_main) | Whether to set this route table as the main route table. | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [prefix\_list\_routes](#input\_prefix\_list\_routes) | A list of route rules for Managed Prefix List. | `list(map(string))` | `[]` | no | -| [propagating\_vpn\_gateways](#input\_propagating\_vpn\_gateways) | A list of Virtual Private Gateway IDs to propagate routes from. | `list(string)` | `[]` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [subnets](#input\_subnets) | A list of subnet IDs to associate with the route table. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | -| [vpc\_gateway\_endpoints](#input\_vpc\_gateway\_endpoints) | A list of the VPC Endpoint IDs with which the Route Table will be associated. | `list(string)` | `[]` | no | +| [name](#input\_name) | (Required) Desired name for the route table resources. | `string` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC which the route table belongs to. | `string` | n/a | yes | +| [gateways](#input\_gateways) | (Optional) A list of gateway IDs to associate with the route table. Only support Internet Gateway and Virtual Private Gateway. | `list(string)` | `[]` | no | +| [ipv4\_routes](#input\_ipv4\_routes) | (Optional) A list of route rules for destinations to IPv4 CIDRs. Each block of `ipv4_routes` as defined below.
(Required) `destination` - The destination IPv4 CIDR block of the route rule.
(Required) `target` - A configuration of the target of the route rule. `target` as defined below.
(Required) `type` - The type of the target of the route rule. Valid values are `CARRIER_GATEWAY`, `CORE_GATEWAY`, `EGRESS_ONLY_INTERNET_GATEWAY`, `INTERNET_GATEWAY`, `VPN_GATEWAY`, `LOCAL_GATEWAY`, `NAT_GATEWAY`, `NETWORK_INTERFACE`, `TRANSIT_GATEWAY`, `VPC_ENDPOINT`, `VPC_PEERING_CONNECTION`.
(Required) `id` - The ID of the target of the route rule. |
list(object({
destination = string

target = object({
type = string
id = string
})
}))
| `[]` | no | +| [ipv6\_routes](#input\_ipv6\_routes) | (Optional) A list of route rules for destinations to IPv6 CIDRs. Each block of `ipv6_routes` as defined below.
(Required) `destination` - The destination IPv6 CIDR block of the route rule.
(Required) `target` - A configuration of the target of the route rule. `target` as defined below.
(Required) `type` - The type of the target of the route rule. Valid values are `CARRIER_GATEWAY`, `CORE_GATEWAY`, `EGRESS_ONLY_INTERNET_GATEWAY`, `INTERNET_GATEWAY`, `VPN_GATEWAY`, `LOCAL_GATEWAY`, `NAT_GATEWAY`, `NETWORK_INTERFACE`, `TRANSIT_GATEWAY`, `VPC_ENDPOINT`, `VPC_PEERING_CONNECTION`.
(Required) `id` - The ID of the target of the route rule. |
list(object({
destination = string

target = object({
type = string
id = string
})
}))
| `[]` | no | +| [is\_main](#input\_is\_main) | (Optional) Whether to set this route table as the main route table. Defaults to `false`. | `bool` | `false` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [prefix\_list\_routes](#input\_prefix\_list\_routes) | (Optional) A list of route rules for destinations to Prefix Lists. Each block of `prefix_list_routes` as defined below.
(Required) `name` - The name of the route rule.
(Required) `destination` - The destination Prefix List of the route rule.
(Required) `target` - A configuration of the target of the route rule. `target` as defined below.
(Required) `type` - The type of the target of the route rule. Valid values are `CARRIER_GATEWAY`, `CORE_GATEWAY`, `EGRESS_ONLY_INTERNET_GATEWAY`, `INTERNET_GATEWAY`, `VPN_GATEWAY`, `LOCAL_GATEWAY`, `NAT_GATEWAY`, `NETWORK_INTERFACE`, `TRANSIT_GATEWAY`, `VPC_ENDPOINT`, `VPC_PEERING_CONNECTION`.
(Required) `id` - The ID of the target of the route rule. |
list(object({
name = string
destination = string

target = object({
type = string
id = string
})
}))
| `[]` | no | +| [propagating\_vpn\_gateways](#input\_propagating\_vpn\_gateways) | (Optional) A list of Virtual Private Gateway IDs to propagate routes from. | `list(string)` | `[]` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [subnets](#input\_subnets) | (Optional) A list of subnet IDs to associate with the route table. | `list(string)` | `[]` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | (Optional) How long to wait for the route table to be created/updated/deleted. |
object({
create = optional(string, "5m")
update = optional(string, "2m")
delete = optional(string, "5m")
})
| `{}` | no | +| [vpc\_gateway\_endpoints](#input\_vpc\_gateway\_endpoints) | (Optional) A list of the VPC Endpoint IDs with which the Route Table will be associated. | `list(string)` | `[]` | no | ## Outputs | Name | Description | |------|-------------| +| [arn](#output\_arn) | The ARN of the routing table. | | [associated\_gateways](#output\_associated\_gateways) | A list of gateway IDs which is associated with the route table. | | [associated\_subnets](#output\_associated\_subnets) | A list of subnet IDs which is associated with the route table. | | [associated\_vpc\_gateway\_endpoints](#output\_associated\_vpc\_gateway\_endpoints) | A list of the VPC Gateway Endpoint IDs which is associated with the route table. | | [id](#output\_id) | The ID of the routing table. | +| [ipv4\_routes](#output\_ipv4\_routes) | A list of route rules for destinations to IPv4 CIDRs. | +| [ipv6\_routes](#output\_ipv6\_routes) | A list of route rules for destinations to IPv6 CIDRs. | | [is\_main](#output\_is\_main) | Whether to set this route table as the main route table. | +| [owner](#output\_owner) | The ID of the AWS account that owns subnets in the routing table. | +| [prefix\_list\_routes](#output\_prefix\_list\_routes) | A list of route rules for destinations to Prefix Lists. | | [propagated\_vpn\_gateways](#output\_propagated\_vpn\_gateways) | A list of Virtual Private Gateway IDs which propagate routes from. | | [vpc\_id](#output\_vpc\_id) | The ID of the VPC which the route table belongs to. | diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf index d9047cf..0b064c4 100644 --- a/modules/route-table/main.tf +++ b/modules/route-table/main.tf @@ -14,9 +14,20 @@ locals { } : {} } + +################################################### +# Route Table +################################################### + resource "aws_route_table" "this" { vpc_id = var.vpc_id + timeouts { + create = var.timeouts.create + update = var.timeouts.update + delete = var.timeouts.delete + } + tags = merge( { "Name" = local.metadata.name @@ -24,6 +35,10 @@ resource "aws_route_table" "this" { local.module_tags, var.tags, ) + + lifecycle { + create_before_destroy = true + } } resource "aws_main_route_table_association" "this" { @@ -31,74 +46,12 @@ resource "aws_main_route_table_association" "this" { vpc_id = var.vpc_id route_table_id = aws_route_table.this.id -} - - -################################################### -# Routes -################################################### - -resource "aws_route" "ipv4" { - for_each = { - for route in var.ipv4_routes : - route.cidr_block => route - } - - route_table_id = aws_route_table.this.id - destination_cidr_block = each.key - - carrier_gateway_id = try(each.value.carrier_gateway_id, null) - egress_only_gateway_id = try(each.value.egress_only_gateway_id, null) - gateway_id = try(each.value.gateway_id, null) - instance_id = try(each.value.instance_id, null) - local_gateway_id = try(each.value.local_gateway_id, null) - nat_gateway_id = try(each.value.nat_gateway_id, null) - network_interface_id = try(each.value.network_interface_id, null) - transit_gateway_id = try(each.value.transit_gateway_id, null) - vpc_endpoint_id = try(each.value.vpc_endpoint_id, null) - vpc_peering_connection_id = try(each.value.vpc_peering_connection_id, null) -} -resource "aws_route" "ipv6" { - for_each = { - for route in var.ipv6_routes : - route.cidr => route + timeouts { + create = var.timeouts.create + update = var.timeouts.update + delete = var.timeouts.delete } - - route_table_id = aws_route_table.this.id - destination_ipv6_cidr_block = each.key - - carrier_gateway_id = try(each.value.carrier_gateway_id, null) - egress_only_gateway_id = try(each.value.egress_only_gateway_id, null) - gateway_id = try(each.value.gateway_id, null) - instance_id = try(each.value.instance_id, null) - local_gateway_id = try(each.value.local_gateway_id, null) - nat_gateway_id = try(each.value.nat_gateway_id, null) - network_interface_id = try(each.value.network_interface_id, null) - transit_gateway_id = try(each.value.transit_gateway_id, null) - vpc_endpoint_id = try(each.value.vpc_endpoint_id, null) - vpc_peering_connection_id = try(each.value.vpc_peering_connection_id, null) -} - -resource "aws_route" "prefix_list" { - for_each = { - for route in var.prefix_list_routes : - route.id => route - } - - route_table_id = aws_route_table.this.id - destination_prefix_list_id = each.key - - carrier_gateway_id = try(each.value.carrier_gateway_id, null) - egress_only_gateway_id = try(each.value.egress_only_gateway_id, null) - gateway_id = try(each.value.gateway_id, null) - instance_id = try(each.value.instance_id, null) - local_gateway_id = try(each.value.local_gateway_id, null) - nat_gateway_id = try(each.value.nat_gateway_id, null) - network_interface_id = try(each.value.network_interface_id, null) - transit_gateway_id = try(each.value.transit_gateway_id, null) - vpc_endpoint_id = try(each.value.vpc_endpoint_id, null) - vpc_peering_connection_id = try(each.value.vpc_peering_connection_id, null) } @@ -106,7 +59,6 @@ resource "aws_route" "prefix_list" { # Associations ################################################### -# INFO: Conflict on create with `for_each` resource "aws_route_table_association" "subnets" { count = length(var.subnets) @@ -115,10 +67,10 @@ resource "aws_route_table_association" "subnets" { } resource "aws_route_table_association" "gateways" { - for_each = toset(var.gateways) + count = length(var.gateways) route_table_id = aws_route_table.this.id - gateway_id = each.value + gateway_id = var.gateways[count.index] } diff --git a/modules/route-table/migrations.tf b/modules/route-table/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/route-table/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/route-table/outputs.tf b/modules/route-table/outputs.tf index e18686e..6502412 100644 --- a/modules/route-table/outputs.tf +++ b/modules/route-table/outputs.tf @@ -8,6 +8,100 @@ output "id" { value = aws_route_table.this.id } +output "arn" { + description = "The ARN of the routing table." + value = aws_route_table.this.arn +} + +output "owner" { + description = "The ID of the AWS account that owns subnets in the routing table." + value = aws_route_table.this.owner_id +} + +output "is_main" { + description = "Whether to set this route table as the main route table." + value = var.is_main +} + +output "ipv4_routes" { + description = "A list of route rules for destinations to IPv4 CIDRs." + value = [ + for route in var.ipv4_routes : { + destination = route.destination + target = { + id = aws_route.ipv4[route.destination].id, + state = aws_route.ipv4[route.destination].state, + type = route.target.type + id = coalesce( + aws_route.ipv4[route.destination].carrier_gateway_id, + aws_route.ipv4[route.destination].core_network_arn, + aws_route.ipv4[route.destination].egress_only_gateway_id, + aws_route.ipv4[route.destination].gateway_id, + aws_route.ipv4[route.destination].local_gateway_id, + aws_route.ipv4[route.destination].nat_gateway_id, + aws_route.ipv4[route.destination].network_interface_id, + aws_route.ipv4[route.destination].transit_gateway_id, + aws_route.ipv4[route.destination].vpc_endpoint_id, + aws_route.ipv4[route.destination].vpc_peering_connection_id, + ) + } + } + ] +} + +output "ipv6_routes" { + description = "A list of route rules for destinations to IPv6 CIDRs." + value = [ + for route in var.ipv6_routes : { + destination = route.destination + target = { + id = aws_route.ipv6[route.destination].id, + state = aws_route.ipv6[route.destination].state, + type = route.target.type + id = coalesce( + aws_route.ipv6[route.destination].carrier_gateway_id, + aws_route.ipv6[route.destination].core_network_arn, + aws_route.ipv6[route.destination].egress_only_gateway_id, + aws_route.ipv6[route.destination].gateway_id, + aws_route.ipv6[route.destination].local_gateway_id, + aws_route.ipv6[route.destination].nat_gateway_id, + aws_route.ipv6[route.destination].network_interface_id, + aws_route.ipv6[route.destination].transit_gateway_id, + aws_route.ipv6[route.destination].vpc_endpoint_id, + aws_route.ipv6[route.destination].vpc_peering_connection_id, + ) + } + } + ] +} + +output "prefix_list_routes" { + description = "A list of route rules for destinations to Prefix Lists." + value = [ + for route in var.prefix_list_routes : { + destination = route.destination + target = { + id = aws_route.prefix_list[route.destination].id, + state = aws_route.prefix_list[route.destination].state, + type = route.target.type + id = coalesce( + aws_route.prefix_list[route.destination].carrier_gateway_id, + aws_route.prefix_list[route.destination].core_network_arn, + aws_route.prefix_list[route.destination].egress_only_gateway_id, + aws_route.prefix_list[route.destination].gateway_id, + aws_route.prefix_list[route.destination].local_gateway_id, + aws_route.prefix_list[route.destination].nat_gateway_id, + aws_route.prefix_list[route.destination].network_interface_id, + aws_route.prefix_list[route.destination].transit_gateway_id, + aws_route.prefix_list[route.destination].vpc_endpoint_id, + aws_route.prefix_list[route.destination].vpc_peering_connection_id, + ) + } + } + ] +} + + output "associated_subnets" { description = "A list of subnet IDs which is associated with the route table." value = aws_route_table_association.subnets[*].subnet_id @@ -15,7 +109,7 @@ output "associated_subnets" { output "associated_gateways" { description = "A list of gateway IDs which is associated with the route table." - value = values(aws_route_table_association.gateways)[*].gateway_id + value = aws_route_table_association.gateways[*].gateway_id } output "associated_vpc_gateway_endpoints" { @@ -27,8 +121,3 @@ output "propagated_vpn_gateways" { description = "A list of Virtual Private Gateway IDs which propagate routes from." value = values(aws_vpn_gateway_route_propagation.this)[*].vpn_gateway_id } - -output "is_main" { - description = "Whether to set this route table as the main route table." - value = var.is_main -} diff --git a/modules/route-table/resource-group.tf b/modules/route-table/resource-group.tf index af108f9..7487ba0 100644 --- a/modules/route-table/resource-group.tf +++ b/modules/route-table/resource-group.tf @@ -7,37 +7,24 @@ locals { replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), ]) ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON } -resource "aws_resourcegroups_group" "this" { + +module "resource_group" { + source = "tedilabs/misc/aws//modules/resource-group" + version = "~> 0.10.0" + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 name = local.resource_group_name description = var.resource_group_description - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query + query = { + resource_tags = local.module_tags } + module_tags_enabled = false tags = merge( - { - "Name" = local.resource_group_name - }, local.module_tags, var.tags, ) diff --git a/modules/route-table/routes.tf b/modules/route-table/routes.tf new file mode 100644 index 0000000..8245014 --- /dev/null +++ b/modules/route-table/routes.tf @@ -0,0 +1,174 @@ +################################################### +# IPv4 Routes +################################################### + +# INFO: Not supported attributes +# - `instance_id` (Deprecated) +resource "aws_route" "ipv4" { + for_each = { + for route in var.ipv4_routes : + route.destination => route + } + + route_table_id = aws_route_table.this.id + destination_cidr_block = each.key + + + ## Targets + carrier_gateway_id = (each.value.target.type == "CARRIER_GATEWAY" + ? each.value.target.id + : null + ) + core_network_arn = (each.value.target.type == "CORE_NETWORK" + ? each.value.target.id + : null + ) + egress_only_gateway_id = (each.value.target.type == "EGRESS_ONLY_INTERNET_GATEWAY" + ? each.value.target.id + : null + ) + gateway_id = (contains(["INTERNET_GATEWAY", "VPN_GATEWAY"], each.value.target.type) + ? each.value.target.id + : null + ) + local_gateway_id = (each.value.target.type == "LOCAL_GATEWAY" + ? each.value.target.id + : null + ) + nat_gateway_id = (each.value.target.type == "NAT_GATEWAY" + ? each.value.target.id + : null + ) + network_interface_id = (each.value.target.type == "NETWORK_INTERFACE" + ? each.value.target.id + : null + ) + transit_gateway_id = (each.value.target.type == "TRANSIT_GATEWAY" + ? each.value.target.id + : null + ) + vpc_endpoint_id = (each.value.target.type == "VPC_ENDPOINT" + ? each.value.target.id + : null + ) + vpc_peering_connection_id = (each.value.target.type == "VPC_PEERING_CONNECTION" + ? each.value.target.id + : null + ) +} + + +################################################### +# IPv6 Routes +################################################### + +resource "aws_route" "ipv6" { + for_each = { + for route in var.ipv6_routes : + route.destination => route + } + + route_table_id = aws_route_table.this.id + destination_ipv6_cidr_block = each.key + + + ## Targets + carrier_gateway_id = (each.value.target.type == "CARRIER_GATEWAY" + ? each.value.target.id + : null + ) + core_network_arn = (each.value.target.type == "CORE_NETWORK" + ? each.value.target.id + : null + ) + egress_only_gateway_id = (each.value.target.type == "EGRESS_ONLY_INTERNET_GATEWAY" + ? each.value.target.id + : null + ) + gateway_id = (contains(["INTERNET_GATEWAY", "VPN_GATEWAY"], each.value.target.type) + ? each.value.target.id + : null + ) + local_gateway_id = (each.value.target.type == "LOCAL_GATEWAY" + ? each.value.target.id + : null + ) + nat_gateway_id = (each.value.target.type == "NAT_GATEWAY" + ? each.value.target.id + : null + ) + network_interface_id = (each.value.target.type == "NETWORK_INTERFACE" + ? each.value.target.id + : null + ) + transit_gateway_id = (each.value.target.type == "TRANSIT_GATEWAY" + ? each.value.target.id + : null + ) + vpc_endpoint_id = (each.value.target.type == "VPC_ENDPOINT" + ? each.value.target.id + : null + ) + vpc_peering_connection_id = (each.value.target.type == "VPC_PEERING_CONNECTION" + ? each.value.target.id + : null + ) +} + + +################################################### +# Prefix List Routes +################################################### + +resource "aws_route" "prefix_list" { + for_each = { + for route in var.prefix_list_routes : + route.name => route + } + + route_table_id = aws_route_table.this.id + destination_prefix_list_id = each.value.destination + + + ## Targets + carrier_gateway_id = (each.value.target.type == "CARRIER_GATEWAY" + ? each.value.target.id + : null + ) + core_network_arn = (each.value.target.type == "CORE_NETWORK" + ? each.value.target.id + : null + ) + egress_only_gateway_id = (each.value.target.type == "EGRESS_ONLY_INTERNET_GATEWAY" + ? each.value.target.id + : null + ) + gateway_id = (contains(["INTERNET_GATEWAY", "VPN_GATEWAY"], each.value.target.type) + ? each.value.target.id + : null + ) + local_gateway_id = (each.value.target.type == "LOCAL_GATEWAY" + ? each.value.target.id + : null + ) + nat_gateway_id = (each.value.target.type == "NAT_GATEWAY" + ? each.value.target.id + : null + ) + network_interface_id = (each.value.target.type == "NETWORK_INTERFACE" + ? each.value.target.id + : null + ) + transit_gateway_id = (each.value.target.type == "TRANSIT_GATEWAY" + ? each.value.target.id + : null + ) + vpc_endpoint_id = (each.value.target.type == "VPC_ENDPOINT" + ? each.value.target.id + : null + ) + vpc_peering_connection_id = (each.value.target.type == "VPC_PEERING_CONNECTION" + ? each.value.target.id + : null + ) +} diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf index edc7b37..b023837 100644 --- a/modules/route-table/variables.tf +++ b/modules/route-table/variables.tf @@ -1,71 +1,151 @@ variable "name" { - description = "Desired name for the route table resources." + description = "(Required) Desired name for the route table resources." type = string + nullable = false } variable "vpc_id" { - description = "The ID of the VPC which the route table belongs to." + description = "(Required) The ID of the VPC which the route table belongs to." type = string + nullable = false +} + +variable "is_main" { + description = "(Optional) Whether to set this route table as the main route table. Defaults to `false`." + type = bool + default = false + nullable = false } variable "subnets" { - description = "A list of subnet IDs to associate with the route table." + description = "(Optional) A list of subnet IDs to associate with the route table." type = list(string) default = [] + nullable = false } variable "gateways" { - description = "A list of gateway IDs to associate with the route table. Only support Internet Gateway and Virtual Private Gateway." + description = "(Optional) A list of gateway IDs to associate with the route table. Only support Internet Gateway and Virtual Private Gateway." type = list(string) default = [] + nullable = false } variable "vpc_gateway_endpoints" { - description = "A list of the VPC Endpoint IDs with which the Route Table will be associated." + description = "(Optional) A list of the VPC Endpoint IDs with which the Route Table will be associated." type = list(string) default = [] + nullable = false } variable "propagating_vpn_gateways" { - description = "A list of Virtual Private Gateway IDs to propagate routes from." + description = "(Optional) A list of Virtual Private Gateway IDs to propagate routes from." type = list(string) default = [] -} - -variable "is_main" { - description = "Whether to set this route table as the main route table." - type = bool - default = false + nullable = false } variable "ipv4_routes" { - description = "A list of route rules for IPv4 CIDRs." - type = list(map(string)) - default = [] + description = < ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 5.3 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 3.45.0 | +| [aws](#provider\_aws) | 5.24.0 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | ## Resources | Name | Type | |------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | | [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [aws_security_group_rule.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_vpc_security_group_egress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [name](#input\_name) | (Required) The name of the security group. | `string` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | (Required) The ID of the associated VPC. | `string` | n/a | yes | | [description](#input\_description) | (Optional) The security group description. This field maps to the AWS `GroupDescription` attribute, for which there is no Update API. | `string` | `"Managed by Terraform."` | no | -| [egress\_rules](#input\_egress\_rules) | (Optional) A list of egress rules in a security group. | `any` | `[]` | no | -| [ingress\_rules](#input\_ingress\_rules) | (Optional) A list of ingress rules in a security group. | `any` | `[]` | no | +| [egress\_rules](#input\_egress\_rules) | (Optional) The configuration for egress rules of the security group. Each block of `egress_rules` as defined below.
(Required) `id` - The ID of the egress rule. This value is only used internally within Terraform code.
(Optional) `description` - The description of the rule.
(Required) `protocol` - The protocol to match. Note that if `protocol` is set to `-1`, it translates to all protocols, all port ranges, and `from_port` and `to_port` values should not be defined.
(Required) `from_port` - The start of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 type.
(Required) `to_port` - The end of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 code.
(Optional) `ipv4_cidrs` - The IPv4 network ranges to allow, in CIDR notation.
(Optional) `ipv6_cidrs` - The IPv6 network ranges to allow, in CIDR notation.
(Optional) `prefix_lists` - The prefix list IDs to allow.
(Optional) `security_groups` - The source security group IDs to allow.
(Optional) `self` - Whether the security group itself will be added as a source to this ingress rule. |
list(object({
id = string
description = optional(string, "Managed by Terraform.")
protocol = string
from_port = number
to_port = number
ipv4_cidrs = optional(list(string), [])
ipv6_cidrs = optional(list(string), [])
prefix_lists = optional(list(string), [])
security_groups = optional(list(string), [])
self = optional(bool, false)
}))
| `[]` | no | +| [ingress\_rules](#input\_ingress\_rules) | (Optional) The configuration for ingress rules of the security group. Each block of `ingress_rules` as defined below.
(Required) `id` - The ID of the ingress rule. This value is only used internally within Terraform code.
(Optional) `description` - The description of the rule.
(Required) `protocol` - The protocol to match. Note that if `protocol` is set to `-1`, it translates to all protocols, all port ranges, and `from_port` and `to_port` values should not be defined.
(Required) `from_port` - The start of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 type.
(Required) `to_port` - The end of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 code.
(Optional) `ipv4_cidrs` - The IPv4 network ranges to allow, in CIDR notation.
(Optional) `ipv6_cidrs` - The IPv6 network ranges to allow, in CIDR notation.
(Optional) `prefix_lists` - The prefix list IDs to allow.
(Optional) `security_groups` - The source security group IDs to allow.
(Optional) `self` - Whether the security group itself will be added as a source to this ingress rule. |
list(object({
id = string
description = optional(string, "Managed by Terraform.")
protocol = string
from_port = number
to_port = number
ipv4_cidrs = optional(list(string), [])
ipv6_cidrs = optional(list(string), [])
prefix_lists = optional(list(string), [])
security_groups = optional(list(string), [])
self = optional(bool, false)
}))
| `[]` | no | | [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [name](#input\_name) | (Optional) The name of the security group. If omitted, Terraform will assign a random, unique name. | `string` | `null` | no | -| [name\_prefix](#input\_name\_prefix) | (Optional) Creates a unique name beginning with the specified prefix. Conflicts with `name`. | `string` | `null` | no | | [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | | [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | | [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | @@ -54,7 +55,10 @@ No modules. | Name | Description | |------|-------------| | [arn](#output\_arn) | The ARN of the security group. | +| [description](#output\_description) | The description of the security group. | +| [egress\_rules](#output\_egress\_rules) | The configuration of the security group egress rules. | | [id](#output\_id) | The ID of the security group. | +| [ingress\_rules](#output\_ingress\_rules) | The configuration of the security group ingress rules. | | [name](#output\_name) | The name of the security group. | | [owner\_id](#output\_owner\_id) | The ID of the AWS account that owns the security group. | | [vpc\_id](#output\_vpc\_id) | The ID of the associated VPC. | diff --git a/modules/security-group/main.tf b/modules/security-group/main.tf index 1dd6c1c..d2b3e93 100644 --- a/modules/security-group/main.tf +++ b/modules/security-group/main.tf @@ -14,11 +14,21 @@ locals { } : {} } + +################################################### +# Security Group +################################################### + +# INFO: Not supported attributes +# - `name_prefix` +# INFO: Use a separate resource +# - `egress` +# - `ingress` resource "aws_security_group" "this" { vpc_id = var.vpc_id - name = var.name - name_prefix = var.name_prefix + name = var.name + # name_prefix = var.name_prefix description = var.description revoke_rules_on_delete = var.revoke_rules_on_delete @@ -31,85 +41,3 @@ resource "aws_security_group" "this" { var.tags, ) } - - -################################################### -# Security Group Rules -################################################### - -locals { - normalized_ingress_rules = [ - for rule in var.ingress_rules : { - id = rule.id - description = lookup(rule, "description", "Managed by Terraform") - - protocol = rule.protocol - from_port = rule.from_port - to_port = rule.to_port - - cidr_blocks = try(sort(compact(rule.cidr_blocks)), null) - ipv6_cidr_blocks = try(sort(compact(rule.ipv6_cidr_blocks)), null) - prefix_list_ids = try(sort(compact(rule.prefix_list_ids)), null) - source_security_group_id = try(rule.source_security_group_id, null) - self = try(rule.self, false) ? true : null - } - ] - normalized_egress_rules = [ - for rule in var.egress_rules : { - id = rule.id - description = lookup(rule, "description", "Managed by Terraform") - - protocol = rule.protocol - from_port = rule.from_port - to_port = rule.to_port - - cidr_blocks = try(sort(compact(rule.cidr_blocks)), null) - ipv6_cidr_blocks = try(sort(compact(rule.ipv6_cidr_blocks)), null) - prefix_list_ids = try(sort(compact(rule.prefix_list_ids)), null) - source_security_group_id = try(rule.source_security_group_id, null) - self = try(rule.self, false) ? true : null - } - ] -} - -resource "aws_security_group_rule" "ingress" { - for_each = { - for rule in local.normalized_ingress_rules : - rule.id => rule - } - - security_group_id = aws_security_group.this.id - type = "ingress" - description = each.value.description - - protocol = each.value.protocol - from_port = each.value.from_port - to_port = each.value.to_port - - cidr_blocks = each.value.cidr_blocks - ipv6_cidr_blocks = each.value.ipv6_cidr_blocks - prefix_list_ids = each.value.prefix_list_ids - source_security_group_id = each.value.source_security_group_id - self = each.value.self -} - -resource "aws_security_group_rule" "egress" { - for_each = { - for rule in local.normalized_egress_rules : - rule.id => rule - } - - security_group_id = aws_security_group.this.id - type = "egress" - description = each.value.description - - protocol = each.value.protocol - from_port = each.value.from_port - to_port = each.value.to_port - - cidr_blocks = each.value.cidr_blocks - ipv6_cidr_blocks = each.value.ipv6_cidr_blocks - prefix_list_ids = each.value.prefix_list_ids - source_security_group_id = each.value.source_security_group_id - self = each.value.self -} diff --git a/modules/security-group/migrations.tf b/modules/security-group/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/security-group/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/security-group/outputs.tf b/modules/security-group/outputs.tf index 2260b4f..e1287bf 100644 --- a/modules/security-group/outputs.tf +++ b/modules/security-group/outputs.tf @@ -13,6 +13,11 @@ output "name" { value = aws_security_group.this.name } +output "description" { + description = "The description of the security group." + value = aws_security_group.this.description +} + output "owner_id" { description = "The ID of the AWS account that owns the security group." value = aws_security_group.this.owner_id @@ -22,3 +27,39 @@ output "vpc_id" { description = "The ID of the associated VPC." value = aws_security_group.this.vpc_id } + +output "ingress_rules" { + description = < { + id = rule.id + arn = rule.arn + description = rule.description + + protocol = rule.ip_protocol + from_port = rule.from_port + to_port = rule.to_port + } + } +} + +output "egress_rules" { + description = < { + id = rule.id + arn = rule.arn + description = rule.description + + protocol = rule.ip_protocol + from_port = rule.from_port + to_port = rule.to_port + } + } +} diff --git a/modules/security-group/resource-group.tf b/modules/security-group/resource-group.tf index af108f9..7487ba0 100644 --- a/modules/security-group/resource-group.tf +++ b/modules/security-group/resource-group.tf @@ -7,37 +7,24 @@ locals { replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), ]) ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON } -resource "aws_resourcegroups_group" "this" { + +module "resource_group" { + source = "tedilabs/misc/aws//modules/resource-group" + version = "~> 0.10.0" + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 name = local.resource_group_name description = var.resource_group_description - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query + query = { + resource_tags = local.module_tags } + module_tags_enabled = false tags = merge( - { - "Name" = local.resource_group_name - }, local.module_tags, var.tags, ) diff --git a/modules/security-group/rules.tf b/modules/security-group/rules.tf new file mode 100644 index 0000000..4a5fdc5 --- /dev/null +++ b/modules/security-group/rules.tf @@ -0,0 +1,250 @@ +locals { + normalized_ingress_rules = concat([], [ + for rule in var.ingress_rules : + concat( + [ + for idx, cidr in rule.ipv4_cidrs : + { + id = "${rule.id}/ipv4/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = cidr + ipv6_cidr = null + prefix_list = null + security_group = null + } + ], + [ + for idx, cidr in rule.ipv6_cidrs : + { + id = "${rule.id}/ipv6/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = cidr + prefix_list = null + security_group = null + } + ], + [ + for idx, prefix_list in rule.prefix_lists : + { + id = "${rule.id}/prefix-list/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = prefix_list + security_group = null + } + ], + [ + for idx, security_group in rule.security_groups : + { + id = "${rule.id}/security-group/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = null + security_group = security_group + } + ], + [ + for self in [rule.self] : + { + id = "${rule.id}/self" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = null + security_group = aws_security_group.this.id + } + if self + ] + ) + ]...) + normalized_egress_rules = concat([], [ + for rule in var.egress_rules : + concat( + [ + for idx, cidr in rule.ipv4_cidrs : + { + id = "${rule.id}/ipv4/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = cidr + ipv6_cidr = null + prefix_list = null + security_group = null + } + ], + [ + for idx, cidr in rule.ipv6_cidrs : + { + id = "${rule.id}/ipv6/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = cidr + prefix_list = null + security_group = null + } + ], + [ + for idx, prefix_list in rule.prefix_lists : + { + id = "${rule.id}/prefix-list/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = prefix_list + security_group = null + } + ], + [ + for idx, security_group in rule.security_groups : + { + id = "${rule.id}/security-group/${idx}" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = null + security_group = security_group + } + ], + [ + for self in [rule.self] : + { + id = "${rule.id}/self" + description = rule.description + + protocol = rule.protocol + from_port = rule.from_port + to_port = rule.to_port + + ipv4_cidr = null + ipv6_cidr = null + prefix_list = null + security_group = aws_security_group.this.id + } + if self + ] + ) + ]...) +} + + +################################################### +# Ingress Rules for Security Group +################################################### + +resource "aws_vpc_security_group_ingress_rule" "this" { + for_each = { + for rule in local.normalized_ingress_rules : + rule.id => rule + } + + security_group_id = aws_security_group.this.id + description = each.value.description + + ip_protocol = each.value.protocol + from_port = (contains(["all", "-1"], each.value.protocol) + ? null + : each.value.from_port + ) + to_port = (contains(["all", "-1"], each.value.protocol) + ? null + : each.value.to_port + ) + + cidr_ipv4 = each.value.ipv4_cidr + cidr_ipv6 = each.value.ipv6_cidr + prefix_list_id = each.value.prefix_list + referenced_security_group_id = each.value.security_group + + tags = merge( + { + "Name" = each.key + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Egress Rules for Security Group +################################################### + +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = { + for rule in local.normalized_egress_rules : + rule.id => rule + } + + security_group_id = aws_security_group.this.id + description = each.value.description + + ip_protocol = each.value.protocol + from_port = (contains(["all", "-1"], each.value.protocol) + ? null + : each.value.from_port + ) + to_port = (contains(["all", "-1"], each.value.protocol) + ? null + : each.value.to_port + ) + + cidr_ipv4 = each.value.ipv4_cidr + cidr_ipv6 = each.value.ipv6_cidr + prefix_list_id = each.value.prefix_list + referenced_security_group_id = each.value.security_group + + tags = merge( + { + "Name" = each.key + }, + local.module_tags, + var.tags, + ) +} diff --git a/modules/security-group/variables.tf b/modules/security-group/variables.tf index 16d0e67..f28506d 100644 --- a/modules/security-group/variables.tf +++ b/modules/security-group/variables.tf @@ -1,54 +1,136 @@ variable "name" { - description = "(Optional) The name of the security group. If omitted, Terraform will assign a random, unique name." + description = "(Required) The name of the security group." type = string - default = null + nullable = false } -variable "name_prefix" { - description = "(Optional) Creates a unique name beginning with the specified prefix. Conflicts with `name`." - type = string - default = null -} +# variable "name_prefix" { +# description = "(Optional) Creates a unique name beginning with the specified prefix. Conflicts with `name`." +# type = string +# default = null +# nullable = true +# } variable "description" { description = "(Optional) The security group description. This field maps to the AWS `GroupDescription` attribute, for which there is no Update API." type = string default = "Managed by Terraform." + nullable = false } variable "vpc_id" { description = "(Required) The ID of the associated VPC." type = string + nullable = false } variable "revoke_rules_on_delete" { description = "(Optional) Instruct Terraform to revoke all of the Security Groups attached ingress and egress rules before deleting the rule itself. This is normally not needed." type = bool default = false + nullable = false } variable "ingress_rules" { - description = "(Optional) A list of ingress rules in a security group." - type = any - default = [] + description = < 0, + length(rule.ipv6_cidrs) > 0, + length(rule.prefix_lists) > 0, + length(rule.security_groups) > 0, + rule.self, + ]) + ]) + error_message = "At least one of `ipv4_cidrs`, `ipv6_cidrs`, `prefix_lists`, `security_groups` or `self` must be specified." + } } variable "egress_rules" { - description = "(Optional) A list of egress rules in a security group." - type = any - default = [] + description = < 0, + length(rule.ipv6_cidrs) > 0, + length(rule.prefix_lists) > 0, + length(rule.security_groups) > 0, + rule.self, + ]) + ]) + error_message = "At least one of `ipv4_cidrs`, `ipv6_cidrs`, `prefix_lists`, `security_groups` or `self` must be specified." + } } variable "tags" { description = "(Optional) A map of tags to add to all resources." type = map(string) default = {} + nullable = false } variable "module_tags_enabled" { description = "(Optional) Whether to create AWS Resource Tags for the module informations." type = bool default = true + nullable = false } @@ -60,16 +142,19 @@ variable "resource_group_enabled" { description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." type = bool default = true + nullable = false } variable "resource_group_name" { description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." type = string default = "" + nullable = false } variable "resource_group_description" { description = "(Optional) The description of Resource Group." type = string default = "Managed by Terraform." + nullable = false } diff --git a/modules/security-group/versions.tf b/modules/security-group/versions.tf index 6078ceb..4cedc8b 100644 --- a/modules/security-group/versions.tf +++ b/modules/security-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = ">= 1.6" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = ">= 5.3" } } } diff --git a/modules/subnet-group/README.md b/modules/subnet-group/README.md index 60b9ae0..337a251 100644 --- a/modules/subnet-group/README.md +++ b/modules/subnet-group/README.md @@ -3,31 +3,35 @@ This module creates following resources. - `aws_subnet` +- `aws_dax_subnet_group` (optional) - `aws_db_subnet_group` (optional) +- `aws_dms_replication_subnet_group` (optional) +- `aws_docdb_subnet_group` (optional) - `aws_elasticache_subnet_group` (optional) -- `aws_redshift_subnet_group` (optional) +- `aws_memorydb_subnet_group` (optional) - `aws_neptune_subnet_group` (optional) -- `aws_docdb_subnet_group` (optional) -- `aws_dax_subnet_group` (optional) -- `aws_dms_replication_subnet_group` (optional) +- `aws_redshift_subnet_group` (optional) ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.71 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 5.22 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.1.0 | +| [aws](#provider\_aws) | 5.22.0 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | +| [share](#module\_share) | tedilabs/account/aws//modules/ram-share | ~> 0.27.0 | ## Resources @@ -37,46 +41,44 @@ No modules. | [aws_db_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource | | [aws_dms_replication_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_replication_subnet_group) | resource | | [aws_docdb_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/docdb_subnet_group) | resource | +| [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | | [aws_elasticache_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_subnet_group) | resource | | [aws_memorydb_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/memorydb_subnet_group) | resource | | [aws_neptune_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/neptune_subnet_group) | resource | | [aws_redshift_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/redshift_subnet_group) | resource | -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | | [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_ec2_transit_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | The name of the subnet group. | `string` | n/a | yes | -| [subnets](#input\_subnets) | A map of subnet parameters to create subnets for the subnet group. | `map(map(any))` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | The ID of the VPC which the subnet group belongs to. | `string` | n/a | yes | -| [assign\_ipv6\_address\_on\_creation](#input\_assign\_ipv6\_address\_on\_creation) | Assign IPv6 address on subnet, must be disabled to change IPv6 CIDRs. This is the IPv6 equivalent of map\_public\_ip\_on\_launch. | `bool` | `false` | no | -| [cache\_subnet\_group\_enabled](#input\_cache\_subnet\_group\_enabled) | Controls if Elasticache Subnet Group should be created. | `bool` | `false` | no | -| [cache\_subnet\_group\_name](#input\_cache\_subnet\_group\_name) | Desired name for the Elasticache Subnet Group. | `string` | `""` | no | -| [customer\_owned\_ipv4\_pool](#input\_customer\_owned\_ipv4\_pool) | The customer owned IPv4 address pool. `outpost_arn` argument must be specified when configured. | `string` | `""` | no | -| [dax\_subnet\_group\_enabled](#input\_dax\_subnet\_group\_enabled) | Controls if DAX Subnet Group should be created. | `bool` | `false` | no | -| [dax\_subnet\_group\_name](#input\_dax\_subnet\_group\_name) | Desired name for the DAX Subnet Group. | `string` | `""` | no | -| [db\_subnet\_group\_enabled](#input\_db\_subnet\_group\_enabled) | Controls if RDS Subnet Group should be created. | `bool` | `false` | no | -| [db\_subnet\_group\_name](#input\_db\_subnet\_group\_name) | Desired name for the RDS Subnet Group. | `string` | `""` | no | -| [dms\_replication\_subnet\_group\_enabled](#input\_dms\_replication\_subnet\_group\_enabled) | Controls if DMS Replication Subnet Group should be created. | `bool` | `false` | no | -| [dms\_replication\_subnet\_group\_name](#input\_dms\_replication\_subnet\_group\_name) | Desired name for the DMS Replication Subnet Group. | `string` | `""` | no | -| [docdb\_subnet\_group\_enabled](#input\_docdb\_subnet\_group\_enabled) | Controls if DocumentDB Subnet Group should be created. | `bool` | `false` | no | -| [docdb\_subnet\_group\_name](#input\_docdb\_subnet\_group\_name) | Desired name for the DocumentDB Subnet Group. | `string` | `""` | no | -| [map\_customer\_owned\_ip\_on\_launch](#input\_map\_customer\_owned\_ip\_on\_launch) | Should be true if network interfaces created in the subnet should be assigned a customer owned IP address. | `bool` | `false` | no | -| [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | Should be false if you do not want to auto-assign public IP on launch. | `bool` | `false` | no | -| [memorydb\_subnet\_group\_enabled](#input\_memorydb\_subnet\_group\_enabled) | Controls if MemoryDB Subnet Group should be created. | `bool` | `false` | no | -| [memorydb\_subnet\_group\_name](#input\_memorydb\_subnet\_group\_name) | Desired name for the MemoryDB Subnet Group. | `string` | `""` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [neptune\_subnet\_group\_enabled](#input\_neptune\_subnet\_group\_enabled) | Controls if Neptune Subnet Group should be created. | `bool` | `false` | no | -| [neptune\_subnet\_group\_name](#input\_neptune\_subnet\_group\_name) | Desired name for the Neptune Subnet Group. | `string` | `""` | no | -| [outpost\_arn](#input\_outpost\_arn) | The ARN of the Outpost. | `string` | `""` | no | -| [redshift\_subnet\_group\_enabled](#input\_redshift\_subnet\_group\_enabled) | Controls if Redshift Subnet Group should be created. | `bool` | `false` | no | -| [redshift\_subnet\_group\_name](#input\_redshift\_subnet\_group\_name) | Desired name for the Redshift Subnet Group. | `string` | `""` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [name](#input\_name) | (Required) The name of the subnet group. | `string` | n/a | yes | +| [subnets](#input\_subnets) | (Required) A configuration of subnets to create in the subnet group. Each block of `subnets` as defined below.
(Optional) `type` - The type of subnet. Valid values are `DUALSTACK` and `IPV6`. Defaults to `DUALSTACK`.
(Optional) `availability_zone` - The availability zone of the subnet. If the value of `availability_zone` and `availability_zone_id` are both not provided, the subnet will be created in random availability zone.
(Optional) `availability_zone_id` - The availability zone ID of the subnet. If the value of `availability_zone` and `availability_zone_id` are both not provided, the subnet will be created in random availability zone.
(Optional) `ipv4_cidr` - The IPv4 CIDR block for the subnet.
(Optional) `ipv6_cidr` - The IPv6 network range for the subnet, in CIDR notation. The subnet size must use a /64 prefix length. |
map(object({
type = optional(string, "DUALSTACK")

availability_zone = optional(string)
availability_zone_id = optional(string)

ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
}))
| n/a | yes | +| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC which the subnet group belongs to. | `string` | n/a | yes | +| [customer\_owned\_ipv4\_address\_assignment](#input\_customer\_owned\_ipv4\_address\_assignment) | (Optional) A configuration for Customer-owned IPv4 address assignment. `customer_owned_ipv4_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a Customer-owned IPv4 address for a new network interface in this subnet. Defaults to `false`.
(Optional) `outpost` - The Amazon Resource Name (ARN) of the Outpost.
(Optional) `pool` - The customer owned IPv4 address pool. |
object({
enabled = optional(bool, false)
outpost = optional(string)
pool = optional(string)
})
| `{}` | no | +| [dax\_subnet\_group](#input\_dax\_subnet\_group) | (Optional) A configuration of DAX Subnet Group. `dax_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DAX Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DAX Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DAX Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [dms\_replication\_subnet\_group](#input\_dms\_replication\_subnet\_group) | (Optional) A configuration of DMS Replication Subnet Group. `dms_replication_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DMS Replication Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DMS Replication Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DMS Replication Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [dns\_config](#input\_dns\_config) | (Optional) A configuration for DNS queries for the subnet. `dns_config` as defined below.
(Optional) `hostname_type` - 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 (`RESOURCE_NAME`). For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address (`IP_NAME`) or the instance ID (`RESOURCE_NAME`). Valid values are `IP_NAME`, `RESOURCE_NAME`. Defaults to `RESOURCE_NAME`.
(Optional) `dns_resource_name_ipv4_enabled` - Whether to respond to DNS queries for instance hostnames with DNS A records. Always `false` for IPv6 only subnet. Defaults to `false`.
(Optional) `dns_resource_name_ipv6_enabled` - Whether to respond to DNS queries for instance hostnames with DNS AAAA records. Always `true` for IPv6 only subnet. Defaults to `false`.
(Optional) `dns64_enabled` - Whether to enable DNS64 to allow IPv6-only services in Amazon VPC to communicate with IPv4-only services and networks. Defaults to `false`. |
object({
hostname_type = optional(string, "RESOURCE_NAME")
dns_resource_name_ipv4_enabled = optional(bool, false)
dns_resource_name_ipv6_enabled = optional(bool, false)
dns64_enabled = optional(bool, false)
})
| `{}` | no | +| [docdb\_subnet\_group](#input\_docdb\_subnet\_group) | (Optional) A configuration of DocumentDB Subnet Group. `docdb_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DocumentDB Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DocumentDB Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DocumentDB Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [elasticache\_subnet\_group](#input\_elasticache\_subnet\_group) | (Optional) A configuration of ElastiCache Subnet Group. `elasticache_subnet_group` as defined below.
(Optional) `enabled` - Whether to create ElastiCache Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the ElastiCache Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the ElastiCache Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [ipv6\_address\_assignment](#input\_ipv6\_address\_assignment) | (Optional) A configuration for IPv6 address assignment. `ipv6_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a IPv6 address for a new network interface in this subnet. Defaults to `false`. |
object({
enabled = optional(bool, false)
})
| `{}` | no | +| [local\_network\_interface\_device\_index](#input\_local\_network\_interface\_device\_index) | (Optional) The device position for local network interfaces in this subnet. For example, `1` indicates local network interfaces in this subnet are the secondary network interface (eth1). A local network interface cannot be the primary network interface (eth0). | `number` | `null` | no | +| [memorydb\_subnet\_group](#input\_memorydb\_subnet\_group) | (Optional) A configuration of MemoryDB Subnet Group. `memorydb_subnet_group` as defined below.
(Optional) `enabled` - Whether to create MemoryDB Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the MemoryDB Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the MemoryDB Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [neptune\_subnet\_group](#input\_neptune\_subnet\_group) | (Optional) A configuration of Neptune Subnet Group. `neptune_subnet_group` as defined below.
(Optional) `enabled` - Whether to create Neptune Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the Neptune Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the Neptune Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [public\_ipv4\_address\_assignment](#input\_public\_ipv4\_address\_assignment) | (Optional) A configuration for public IPv4 address assignment. `public_ipv4_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a public IPv4 address for a new network interface in this subnet. Defaults to `false`. |
object({
enabled = optional(bool, false)
})
| `{}` | no | +| [rds\_subnet\_group](#input\_rds\_subnet\_group) | (Optional) A configuration of RDS Subnet Group. `rds_subnet_group` as defined below.
(Optional) `enabled` - Whether to create RDS Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the RDS Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the RDS Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [redshift\_subnet\_group](#input\_redshift\_subnet\_group) | (Optional) A configuration of Redshift Subnet Group. `redshift_subnet_group` as defined below.
(Optional) `enabled` - Whether to create Redshift Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the Redshift Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the Redshift Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [shares](#input\_shares) | (Optional) A list of resource shares via RAM (Resource Access Manager). |
list(object({
name = optional(string)

permissions = optional(set(string), ["AWSRAMDefaultPermissionSubnet"])

external_principals_allowed = optional(bool, false)
principals = optional(set(string), [])

tags = optional(map(string), {})
}))
| `[]` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | (Optional) How long to wait for the subnet group to be created/deleted. |
object({
create = optional(string, "10m")
delete = optional(string, "20m")
})
| `{}` | no | +| [transit\_gateway\_attachments](#input\_transit\_gateway\_attachments) | (Optional) A list of configurations for Transit Gateway VPC attachments. Each block of `transit_gateway_attachments` as defined below.
(Required) `name` - The name of the Transit Gateway VPC attachment.
(Required) `transit_gateway` - The ID of the Transit Gateway.
(Optional) `appliance_mode_enabled` - Whether Appliance Mode support is enabled. If enabled, a traffic flow between a source and destination uses the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults to `false`.
(Optional) `dns_support_enabled` - Whether to enable Domain Name System resolution for VPCs attached to this transit gateway. Defaults to `true`.
(Optional) `ipv6_enabled` - Whether to enable IPv6 support. Defaults to `false`.
(Optional) `default_association_route_table_enabled` - Whether to automatically associate transit gateway attachments with this transit gateway's default route table. This cannot be configured or perform drift detection with Resource Access Manager shared EC2 Transit Gateways. Defaults to `false`.
(Optional) `default_propagation_route_table_enabled` - Whether to automatically propagate transit gateway attachments with this transit gateway's default route table. This cannot be configured or perform drift detection with Resource Access Manager shared EC2 Transit Gateways. Defaults to `false`.
(Optional) `tags` - A map of tags to add to the vpc association. |
list(object({
name = string
transit_gateway = string
appliance_mode_enabled = optional(bool, false)
dns_support_enabled = optional(bool, true)
ipv6_enabled = optional(bool, false)
default_association_route_table_enabled = optional(bool, false)
default_propagation_route_table_enabled = optional(bool, false)

tags = optional(map(string), {})
}))
| `[]` | no | ## Outputs @@ -85,24 +87,27 @@ No modules. | [arns](#output\_arns) | A list of ARNs of subnets | | [availability\_zone\_ids](#output\_availability\_zone\_ids) | A list of availability zone IDs which the subnet group uses. | | [availability\_zones](#output\_availability\_zones) | A list of availability zones which the subnet group uses. | -| [cache\_subnet\_group\_id](#output\_cache\_subnet\_group\_id) | The ID of the Elasticache Subnet Group. | -| [cidr\_blocks](#output\_cidr\_blocks) | The CIDR blocks of the subnet group. | -| [dax\_subnet\_group\_id](#output\_dax\_subnet\_group\_id) | The ID of the DAX Subnet Group. | -| [db\_subnet\_group\_arn](#output\_db\_subnet\_group\_arn) | The ARN of the RDS Subnet Group. | -| [db\_subnet\_group\_id](#output\_db\_subnet\_group\_id) | The ID of the RDS Subnet Group. | -| [dms\_replication\_subnet\_group\_id](#output\_dms\_replication\_subnet\_group\_id) | The ID of the DMS Replication Subnet Group. | -| [docdb\_subnet\_group\_arn](#output\_docdb\_subnet\_group\_arn) | The ARN of the DocumentDB Subnet Group. | -| [docdb\_subnet\_group\_id](#output\_docdb\_subnet\_group\_id) | The ID of the DocumentDB Subnet Group. | +| [customer\_owned\_ipv4\_address\_assignment](#output\_customer\_owned\_ipv4\_address\_assignment) | The configuration of Customer-owned IPv4 address assignment.
`enabled` - Whether to automatically assign Customer-owned IPv4 address to instances launched in the subnet group.
`outpost` - The ARN of the Outpost.
`pool` - The ID of the Customer-owned IPv4 address pool. | +| [dax\_subnet\_group](#output\_dax\_subnet\_group) | The configuration of DAX Subnet Group.
`id` - The ID of the DAX Subnet Group.
`name` - The name of the DAX Subnet Group.
`description` - The description of the DAX Subnet Group. | +| [dms\_replication\_subnet\_group](#output\_dms\_replication\_subnet\_group) | The configuration of DMS Replication Subnet Group.
`id` - The ID of the DMS Replication Subnet Group.
`arn` - The ARN of the DMS Replication Subnet Group.
`name` - The name of the DMS Replication Subnet Group.
`description` - The description of the DMS Replication Subnet Group. | +| [dns\_config](#output\_dns\_config) | The DNS configuration for the subnet group.
`id` - The ID of the DAX Subnet Group. | +| [docdb\_subnet\_group](#output\_docdb\_subnet\_group) | The configuration of DocumentDB Subnet Group.
`id` - The ID of the DocumentDB Subnet Group.
`arn` - The ARN of the DocumentDB Subnet Group.
`name` - The name of the DocumentDB Subnet Group.
`description` - The description of the DocumentDB Subnet Group. | +| [elasticache\_subnet\_group](#output\_elasticache\_subnet\_group) | The configuration of ElastiCache Subnet Group.
`id` - The ID of the ElastiCache Subnet Group.
`arn` - The ARN of the ElastiCache Subnet Group.
`name` - The name of the ElastiCache Subnet Group.
`description` - The description of the ElastiCache Subnet Group. | | [ids](#output\_ids) | A list of IDs of subnets | -| [ipv6\_cidr\_blocks](#output\_ipv6\_cidr\_blocks) | The IPv6 CIDR blocks of the subnet group. | -| [memorydb\_subnet\_group\_arn](#output\_memorydb\_subnet\_group\_arn) | The ARN of the MemoryDB Subnet Group. | -| [memorydb\_subnet\_group\_id](#output\_memorydb\_subnet\_group\_id) | The ID of the MemoryDB Subnet Group. | +| [ipv4\_cidrs](#output\_ipv4\_cidrs) | The IPv4 CIDR blocks of the subnet group. | +| [ipv6\_address\_assignment](#output\_ipv6\_address\_assignment) | The configuration of IPv6 address assignment.
`enabled` - Whether to automatically assign IPv6 address to instances launched in the subnet group. | +| [ipv6\_cidrs](#output\_ipv6\_cidrs) | The IPv6 CIDR blocks of the subnet group. | +| [local\_network\_interface\_device\_index](#output\_local\_network\_interface\_device\_index) | The device position for local network interfaces in this subnet. | +| [memorydb\_subnet\_group](#output\_memorydb\_subnet\_group) | The configuration of MemoryDB Subnet Group.
`id` - The ID of the MemoryDB Subnet Group.
`arn` - The ARN of the MemoryDB Subnet Group.
`name` - The name of the MemoryDB Subnet Group.
`description` - The description of the MemoryDB Subnet Group. | | [name](#output\_name) | The name of the subnet group. | -| [neptune\_subnet\_group\_arn](#output\_neptune\_subnet\_group\_arn) | The ARN of the Neptune Subnet Group. | -| [neptune\_subnet\_group\_id](#output\_neptune\_subnet\_group\_id) | The ID of the Neptune DB Subnet Group. | -| [redshift\_subnet\_group\_arn](#output\_redshift\_subnet\_group\_arn) | The ARN of the Redshift Subnet Group. | -| [redshift\_subnet\_group\_id](#output\_redshift\_subnet\_group\_id) | The ID of the Redshift Subnet Group. | +| [neptune\_subnet\_group](#output\_neptune\_subnet\_group) | The configuration of Neptune Subnet Group.
`id` - The ID of the Neptune Subnet Group.
`arn` - The ARN of the Neptune Subnet Group.
`name` - The name of the Neptune Subnet Group.
`description` - The description of the Neptune Subnet Group. | +| [owner](#output\_owner) | The ID of the AWS account that owns subnets in the subnet group. | +| [public\_ipv4\_address\_assignment](#output\_public\_ipv4\_address\_assignment) | The configuration of public IPv4 address assignment.
`enabled` - Whether to automatically assign public IPv4 address to instances launched in the subnet group. | +| [rds\_subnet\_group](#output\_rds\_subnet\_group) | The configuration of RDS Subnet Group.
`id` - The ID of the RDS Subnet Group.
`arn` - The ARN of the RDS Subnet Group.
`name` - The name of the RDS Subnet Group.
`description` - The description of the RDS Subnet Group. | +| [redshift\_subnet\_group](#output\_redshift\_subnet\_group) | The configuration of Redshift Subnet Group.
`id` - The ID of the Redshift Subnet Group.
`arn` - The ARN of the Redshift Subnet Group.
`name` - The name of the Redshift Subnet Group.
`description` - The description of the Redshift Subnet Group. | +| [sharing](#output\_sharing) | The configuration for sharing of subnets in the subnet group.
`status` - An indication of whether subnets are shared with other AWS accounts, or was shared with the current account by another AWS account. Sharing is configured through AWS Resource Access Manager (AWS RAM). Values are `NOT_SHARED`, `SHARED_BY_ME` or `SHARED_WITH_ME`.
`shares` - The list of resource shares via RAM (Resource Access Manager). | | [subnets](#output\_subnets) | A list of subnets of the subnet group. | | [subnets\_by\_az](#output\_subnets\_by\_az) | A map of subnets of the subnet group which are grouped by availability zone id. | +| [transit\_gateway\_attachments](#output\_transit\_gateway\_attachments) | The configuration of Transit Gateway VPC attachments. | | [vpc\_id](#output\_vpc\_id) | The ID of the VPC which the subnet group belongs to. | diff --git a/modules/subnet-group/integrations.tf b/modules/subnet-group/integrations.tf new file mode 100644 index 0000000..28c8135 --- /dev/null +++ b/modules/subnet-group/integrations.tf @@ -0,0 +1,226 @@ +data "aws_caller_identity" "this" {} + +locals { + account_id = data.aws_caller_identity.this.account_id +} + + +################################################### +# VPC Attachments for Transit Gateway +################################################### + +data "aws_ec2_transit_gateway" "this" { + for_each = { + for attachment in var.transit_gateway_attachments : + attachment.name => attachment.transit_gateway + } + + filter { + name = "transit-gateway-id" + values = [each.value] + } +} + +resource "aws_ec2_transit_gateway_vpc_attachment" "this" { + for_each = { + for attachment in var.transit_gateway_attachments : + attachment.name => attachment + } + + vpc_id = var.vpc_id + subnet_ids = values(aws_subnet.this)[*].id + + transit_gateway_id = each.value.transit_gateway + + appliance_mode_support = each.value.appliance_mode_enabled ? "enable" : "disable" + dns_support = each.value.dns_support_enabled ? "enable" : "disable" + ipv6_support = each.value.ipv6_enabled ? "enable" : "disable" + transit_gateway_default_route_table_association = (local.account_id == data.aws_ec2_transit_gateway.this[each.key].owner_id + ? each.value.default_association_route_table_enabled + : null + ) + transit_gateway_default_route_table_propagation = (local.account_id == data.aws_ec2_transit_gateway.this[each.key].owner_id + ? each.value.default_propagation_route_table_enabled + : null + ) + + tags = merge( + { + "Name" = each.key + }, + local.module_tags, + var.tags, + each.value.tags, + ) +} + + +################################################### +# Subnet Group for DAX +################################################### + +resource "aws_dax_subnet_group" "this" { + count = var.dax_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.dax_subnet_group.name, var.name) + description = var.dax_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + # INFO: Not support resource tags + # tags = {} +} + + +################################################### +# Subnet Group for DMS Replication +################################################### + +resource "aws_dms_replication_subnet_group" "this" { + count = var.dms_replication_subnet_group.enabled ? 1 : 0 + + replication_subnet_group_id = coalesce(var.dms_replication_subnet_group.name, var.name) + replication_subnet_group_description = var.dms_replication_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.dms_replication_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for DocumentDB +################################################### + +resource "aws_docdb_subnet_group" "this" { + count = var.docdb_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.docdb_subnet_group.name, var.name) + description = var.docdb_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.docdb_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for ElastiCache +################################################### + +resource "aws_elasticache_subnet_group" "this" { + count = var.elasticache_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.elasticache_subnet_group.name, var.name) + description = var.elasticache_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.elasticache_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for MemoryDB +################################################### + +resource "aws_memorydb_subnet_group" "this" { + count = var.memorydb_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.memorydb_subnet_group.name, var.name) + description = var.memorydb_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.memorydb_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for Neptune +################################################### + +resource "aws_neptune_subnet_group" "this" { + count = var.neptune_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.neptune_subnet_group.name, var.name) + description = var.neptune_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.neptune_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for RDS +################################################### + +resource "aws_db_subnet_group" "this" { + count = var.rds_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.rds_subnet_group.name, var.name) + description = var.rds_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.rds_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for Redshift +################################################### + +resource "aws_redshift_subnet_group" "this" { + count = var.redshift_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.redshift_subnet_group.name, var.name) + description = var.redshift_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.redshift_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} diff --git a/modules/subnet-group/main.tf b/modules/subnet-group/main.tf index 4d51a2a..4beec77 100644 --- a/modules/subnet-group/main.tf +++ b/modules/subnet-group/main.tf @@ -14,6 +14,25 @@ locals { } : {} } +data "aws_availability_zones" "available" { + state = "available" +} + +locals { + available_availablity_zones = data.aws_availability_zones.available.names + available_availablity_zone_ids = data.aws_availability_zones.available.zone_ids + + az = { + for idx, id in local.available_availablity_zone_ids : + id => local.available_availablity_zones[idx] + } + + hostname_types = { + "RESOURCE_NAME" = "resource-name" + "IP_NAME" = "ip-name" + } +} + locals { availability_zones = distinct( values(aws_subnet.this)[*].availability_zone @@ -21,167 +40,93 @@ locals { availability_zone_ids = distinct( values(aws_subnet.this)[*].availability_zone_id ) -} - -locals { subnets = [ - for subnet in aws_subnet.this : { + for name, subnet in aws_subnet.this : { id = subnet.id arn = subnet.arn - name = subnet.tags["Name"] + name = name availability_zone = subnet.availability_zone availability_zone_id = subnet.availability_zone_id - cidr_block = subnet.cidr_block - ipv6_cidr_block = subnet.ipv6_cidr_block + ipv4_cidr = subnet.cidr_block + ipv6_cidr = subnet.ipv6_cidr_block } ] } + +################################################### +# Subnets of the Subnet Group +################################################### + resource "aws_subnet" "this" { for_each = var.subnets vpc_id = var.vpc_id - availability_zone = lookup(each.value, "availability_zone", null) - availability_zone_id = lookup(each.value, "availability_zone_id", null) - - cidr_block = lookup(each.value, "cidr_block", "") - ipv6_cidr_block = lookup(each.value, "ipv6_cidr_block", null) + availability_zone = each.value.availability_zone + availability_zone_id = each.value.availability_zone_id - map_public_ip_on_launch = var.map_public_ip_on_launch - assign_ipv6_address_on_creation = var.assign_ipv6_address_on_creation - - outpost_arn = var.outpost_arn - customer_owned_ipv4_pool = var.customer_owned_ipv4_pool - map_customer_owned_ip_on_launch = var.map_customer_owned_ip_on_launch - - tags = merge( - { - "Name" = each.key - }, - local.module_tags, - var.tags, - ) -} + enable_lni_at_device_index = var.local_network_interface_device_index -################################################### -# Subnet Groups for Managed Data Services -################################################### + ## IP CIDR Blocks + ipv6_native = each.value.type == "IPV6" -resource "aws_db_subnet_group" "this" { - count = var.db_subnet_group_enabled ? 1 : 0 + cidr_block = each.value.ipv4_cidr + ipv6_cidr_block = each.value.ipv6_cidr - name = var.db_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - tags = merge( - { - "Name" = var.db_subnet_group_name - }, - local.module_tags, - var.tags, + ## IP Assignments + map_public_ip_on_launch = (each.value.type == "IPV6" + ? false + : var.public_ipv4_address_assignment.enabled ) -} - -resource "aws_elasticache_subnet_group" "this" { - count = var.cache_subnet_group_enabled ? 1 : 0 - - name = var.cache_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.cache_subnet_group_name - }, - local.module_tags, - var.tags, + assign_ipv6_address_on_creation = (each.value.type == "IPV6" + ? true + : var.ipv6_address_assignment.enabled ) -} - -resource "aws_redshift_subnet_group" "this" { - count = var.redshift_subnet_group_enabled ? 1 : 0 - - name = var.redshift_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.redshift_subnet_group_name - }, - local.module_tags, - var.tags, + map_customer_owned_ip_on_launch = (each.value.type == "IPV6" + ? null + : (var.customer_owned_ipv4_address_assignment.enabled + ? true + : null + ) ) -} - -resource "aws_neptune_subnet_group" "this" { - count = var.neptune_subnet_group_enabled ? 1 : 0 - - name = var.neptune_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.neptune_subnet_group_name - }, - local.module_tags, - var.tags, + outpost_arn = (var.customer_owned_ipv4_address_assignment.enabled + ? var.customer_owned_ipv4_address_assignment.outpost + : null ) -} - -resource "aws_docdb_subnet_group" "this" { - count = var.docdb_subnet_group_enabled ? 1 : 0 - - name = var.docdb_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.docdb_subnet_group_name - }, - local.module_tags, - var.tags, + customer_owned_ipv4_pool = (var.customer_owned_ipv4_address_assignment.enabled + ? var.customer_owned_ipv4_address_assignment.pool + : null ) -} - -resource "aws_dax_subnet_group" "this" { - count = var.dax_subnet_group_enabled ? 1 : 0 - - name = var.dax_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - # INFO: Not support resource tags - # tags = {} -} - -resource "aws_dms_replication_subnet_group" "this" { - count = var.dms_replication_subnet_group_enabled ? 1 : 0 - - replication_subnet_group_id = var.dms_replication_subnet_group_name - replication_subnet_group_description = "Managed by Terraform." - subnet_ids = values(aws_subnet.this)[*].id - tags = merge( - { - "Name" = var.dms_replication_subnet_group_name - }, - local.module_tags, - var.tags, + ## DNS Configurations + private_dns_hostname_type_on_launch = (each.value.type == "IPV6" + ? "resource-name" + : local.hostname_types[var.dns_config.hostname_type] ) -} + enable_resource_name_dns_a_record_on_launch = (each.value.type == "IPV6" + ? false + : var.dns_config.dns_resource_name_ipv4_enabled + ) + enable_resource_name_dns_aaaa_record_on_launch = (each.value.type == "IPV6" + ? true + : var.dns_config.dns_resource_name_ipv6_enabled + ) + enable_dns64 = var.dns_config.dns64_enabled -resource "aws_memorydb_subnet_group" "this" { - count = var.memorydb_subnet_group_enabled ? 1 : 0 - name = var.memorydb_subnet_group_name - description = "Managed by Terraform." - subnet_ids = values(aws_subnet.this)[*].id + timeouts { + create = var.timeouts.create + delete = var.timeouts.delete + } tags = merge( { - "Name" = var.memorydb_subnet_group_name + "Name" = each.key }, local.module_tags, var.tags, diff --git a/modules/subnet-group/migrations.tf b/modules/subnet-group/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/subnet-group/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/subnet-group/outputs.tf b/modules/subnet-group/outputs.tf index 3150a0b..980f36d 100644 --- a/modules/subnet-group/outputs.tf +++ b/modules/subnet-group/outputs.tf @@ -5,7 +5,7 @@ output "name" { output "vpc_id" { description = "The ID of the VPC which the subnet group belongs to." - value = var.vpc_id + value = values(aws_subnet.this)[0].vpc_id } output "ids" { @@ -18,12 +18,17 @@ output "arns" { value = values(aws_subnet.this)[*].arn } -output "cidr_blocks" { - description = "The CIDR blocks of the subnet group." - value = values(aws_subnet.this)[*].cidr_block +output "owner" { + description = "The ID of the AWS account that owns subnets in the subnet group." + value = values(aws_subnet.this)[0].owner_id } -output "ipv6_cidr_blocks" { +output "ipv4_cidrs" { + description = "The IPv4 CIDR blocks of the subnet group." + value = compact(values(aws_subnet.this)[*].cidr_block) +} + +output "ipv6_cidrs" { description = "The IPv6 CIDR blocks of the subnet group." value = compact(values(aws_subnet.this)[*].ipv6_cidr_block) } @@ -51,85 +56,240 @@ output "subnets_by_az" { } } -output "db_subnet_group_id" { - description = "The ID of the RDS Subnet Group." - value = try(aws_db_subnet_group.this.*.id[0], null) +output "local_network_interface_device_index" { + description = "The device position for local network interfaces in this subnet." + value = var.local_network_interface_device_index } -output "db_subnet_group_arn" { - description = "The ARN of the RDS Subnet Group." - value = try(aws_db_subnet_group.this.*.arn[0], null) +output "public_ipv4_address_assignment" { + description = < k + }[values(aws_subnet.this)[0].private_dns_hostname_type_on_launch] + dns_resource_name_ipv4_enabled = values(aws_subnet.this)[0].enable_resource_name_dns_a_record_on_launch + dns_resource_name_ipv6_enabled = values(aws_subnet.this)[0].enable_resource_name_dns_aaaa_record_on_launch + dns64_enabled = values(aws_subnet.this)[0].enable_dns64 + } } -output "neptune_subnet_group_id" { - description = "The ID of the Neptune DB Subnet Group." - value = try(aws_neptune_subnet_group.this.*.id[0], null) +output "transit_gateway_attachments" { + description = < { + name = name + transit_gateway = attachment.transit_gateway_id + + appliance_mode_enabled = attachment.appliance_mode_support == "enable" + dns_support_enabled = attachment.dns_support == "enable" + ipv6_enabled = attachment.ipv6_support == "enable" + default_association_route_table_enabled = attachment.transit_gateway_default_route_table_association + default_propagation_route_table_enabled = attachment.transit_gateway_default_route_table_propagation + } + } } -output "neptune_subnet_group_arn" { - description = "The ARN of the Neptune Subnet Group." - value = try(aws_neptune_subnet_group.this.*.arn[0], null) +output "dax_subnet_group" { + description = < 0 ? "SHARED_BY_ME" : "NOT_SHARED" + shares = module.share + } } diff --git a/modules/subnet-group/ram-share.tf b/modules/subnet-group/ram-share.tf new file mode 100644 index 0000000..9f5d4a5 --- /dev/null +++ b/modules/subnet-group/ram-share.tf @@ -0,0 +1,31 @@ +################################################### +# Resource Sharing by RAM (Resource Access Manager) +################################################### + +module "share" { + source = "tedilabs/account/aws//modules/ram-share" + version = "~> 0.27.0" + + for_each = { + for share in var.shares : + share.name => share + } + + name = "vpc.subnet-group.${var.name}.${each.key}" + + resources = values(aws_subnet.this)[*].arn + + permissions = each.value.permissions + + external_principals_allowed = each.value.external_principals_allowed + principals = each.value.principals + + resource_group_enabled = false + module_tags_enabled = false + + tags = merge( + local.module_tags, + var.tags, + each.value.tags, + ) +} diff --git a/modules/subnet-group/resource-group.tf b/modules/subnet-group/resource-group.tf index af108f9..7487ba0 100644 --- a/modules/subnet-group/resource-group.tf +++ b/modules/subnet-group/resource-group.tf @@ -7,37 +7,24 @@ locals { replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), ]) ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON } -resource "aws_resourcegroups_group" "this" { + +module "resource_group" { + source = "tedilabs/misc/aws//modules/resource-group" + version = "~> 0.10.0" + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 name = local.resource_group_name description = var.resource_group_description - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query + query = { + resource_tags = local.module_tags } + module_tags_enabled = false tags = merge( - { - "Name" = local.resource_group_name - }, local.module_tags, var.tags, ) diff --git a/modules/subnet-group/variables.tf b/modules/subnet-group/variables.tf index b662911..8d5aa8f 100644 --- a/modules/subnet-group/variables.tf +++ b/modules/subnet-group/variables.tf @@ -1,154 +1,321 @@ variable "name" { - description = "The name of the subnet group." + description = "(Required) The name of the subnet group." type = string + nullable = false } variable "vpc_id" { - description = "The ID of the VPC which the subnet group belongs to." + description = "(Required) The ID of the VPC which the subnet group belongs to." type = string + nullable = false } variable "subnets" { - description = "A map of subnet parameters to create subnets for the subnet group." - type = map(map(any)) -} + description = < 0 + error_message = "At least one subnet must be provided." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + contains(["DUALSTACK", "IPV6"], subnet.type) + ]) + error_message = "Valid values for `type` of each subnet are `DUALSTACK` and `IPV6`." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + subnet.ipv4_cidr != null + if subnet.type == "DUALSTACK" + ]) + error_message = "IPv4 CIDR block must be provided for `DUALSTACK` subnet." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + subnet.ipv6_cidr != null && subnet.ipv4_cidr == null + if subnet.type == "IPV6" + ]) + error_message = "IPv6 CIDR block must be provided for `IPV6` subnet." + } } -variable "customer_owned_ipv4_pool" { - description = "The customer owned IPv4 address pool. `outpost_arn` argument must be specified when configured." - type = string - default = "" +variable "local_network_interface_device_index" { + description = < -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.50.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_endpoint_connection_notification.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint_connection_notification) | resource | -| [aws_vpc_endpoint_service.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint_service) | resource | -| [aws_vpc_endpoint_service_allowed_principal.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint_service_allowed_principal) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the VPC Endpoint Service. | `string` | n/a | yes | -| [acceptance\_required](#input\_acceptance\_required) | Whether or not VPC endpoint connection requests to the service must be accepted by the service owner. | `bool` | `false` | no | -| [allowed\_principals](#input\_allowed\_principals) | A list of the ARNs of principal to allow to discover a VPC endpoint service. | `list(string)` | `[]` | no | -| [gateway\_load\_balancer\_arns](#input\_gateway\_load\_balancer\_arns) | List of Amazon Resource Names of one or more Gateway Load Balancers for the endpoint service. | `list(string)` | `null` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [network\_load\_balancer\_arns](#input\_network\_load\_balancer\_arns) | List of Amazon Resource Names of one or more Network Load Balancers for the endpoint service. | `list(string)` | `null` | no | -| [notification\_configurations](#input\_notification\_configurations) | A list of configurations of Endpoint Connection Notifications for VPC Endpoint events. |
list(object({
sns_arn = string
events = list(string)
}))
| `[]` | no | -| [private\_domain](#input\_private\_domain) | The private domain name for the service. | `string` | `null` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [allowed\_principals](#output\_allowed\_principals) | A list of the ARNs of allowed principals to discover a VPC endpoint service. | -| [arn](#output\_arn) | The Amazon Resource Name (ARN) of the VPC endpoint service. | -| [availability\_zones](#output\_availability\_zones) | The Availability Zones in which the service is available. | -| [base\_domain\_names](#output\_base\_domain\_names) | The DNS names for the service. | -| [gateway\_load\_balancer\_arns](#output\_gateway\_load\_balancer\_arns) | ARNs of Gateway Load Balancers which is associated to the endpoint service. | -| [id](#output\_id) | The ID of the VPC endpoint service. | -| [manages\_vpc\_endpoints](#output\_manages\_vpc\_endpoints) | Whether or not the service manages its VPC endpoints | -| [name](#output\_name) | The VPC Endpoint Service name. | -| [network\_load\_balancer\_arns](#output\_network\_load\_balancer\_arns) | ARNs of Network Load Balancers which is associated to the endpoint service. | -| [notification\_configurations](#output\_notification\_configurations) | A list of Endpoint Connection Notifications for VPC Endpoint events. | -| [private\_domain](#output\_private\_domain) | The private DNS name for the service. | -| [private\_domain\_configurations](#output\_private\_domain\_configurations) | List of objects containing information about the endpoint service private DNS name configuration. | -| [service\_name](#output\_service\_name) | The service name. | -| [service\_type](#output\_service\_type) | The service type, `Gateway` or `Interface`. | -| [state](#output\_state) | The state of the VPC endpoint service. | - diff --git a/modules/vpc-endpoint-service/main.tf b/modules/vpc-endpoint-service/main.tf deleted file mode 100644 index 69d7ab2..0000000 --- a/modules/vpc-endpoint-service/main.tf +++ /dev/null @@ -1,60 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -resource "aws_vpc_endpoint_service" "this" { - gateway_load_balancer_arns = var.gateway_load_balancer_arns - network_load_balancer_arns = var.network_load_balancer_arns - - private_dns_name = var.private_domain - acceptance_required = var.acceptance_required - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - - -################################################### -# Allowed Principals -################################################### - -resource "aws_vpc_endpoint_service_allowed_principal" "this" { - for_each = toset(var.allowed_principals) - - vpc_endpoint_service_id = aws_vpc_endpoint_service.this.id - principal_arn = each.value -} - - -################################################### -# Notification -################################################### - -resource "aws_vpc_endpoint_connection_notification" "this" { - for_each = { - for config in try(var.notification_configurations, []) : - config.sns_arn => config - } - - vpc_endpoint_service_id = aws_vpc_endpoint_service.this.id - - connection_notification_arn = each.key - connection_events = try(each.value.events, []) -} diff --git a/modules/vpc-endpoint-service/outputs.tf b/modules/vpc-endpoint-service/outputs.tf deleted file mode 100644 index 9fd117f..0000000 --- a/modules/vpc-endpoint-service/outputs.tf +++ /dev/null @@ -1,74 +0,0 @@ -output "name" { - description = "The VPC Endpoint Service name." - value = var.name -} - -output "id" { - description = "The ID of the VPC endpoint service." - value = aws_vpc_endpoint_service.this.id -} - -output "arn" { - description = "The Amazon Resource Name (ARN) of the VPC endpoint service." - value = aws_vpc_endpoint_service.this.arn -} - -output "state" { - description = "The state of the VPC endpoint service." - value = aws_vpc_endpoint_service.this.state -} - -output "service_name" { - description = "The service name." - value = aws_vpc_endpoint_service.this.service_name -} - -output "service_type" { - description = "The service type, `Gateway` or `Interface`." - value = aws_vpc_endpoint_service.this.service_type -} - -output "gateway_load_balancer_arns" { - description = "ARNs of Gateway Load Balancers which is associated to the endpoint service." - value = aws_vpc_endpoint_service.this.gateway_load_balancer_arns -} - -output "network_load_balancer_arns" { - description = "ARNs of Network Load Balancers which is associated to the endpoint service." - value = aws_vpc_endpoint_service.this.network_load_balancer_arns -} - -output "availability_zones" { - description = "The Availability Zones in which the service is available." - value = aws_vpc_endpoint_service.this.availability_zones -} - -output "allowed_principals" { - description = "A list of the ARNs of allowed principals to discover a VPC endpoint service." - value = var.allowed_principals -} - -output "manages_vpc_endpoints" { - description = "Whether or not the service manages its VPC endpoints" - value = aws_vpc_endpoint_service.this.manages_vpc_endpoints -} - -output "base_domain_names" { - description = "The DNS names for the service." - value = aws_vpc_endpoint_service.this.base_endpoint_dns_names -} - -output "private_domain" { - description = "The private DNS name for the service." - value = aws_vpc_endpoint_service.this.private_dns_name -} - -output "private_domain_configurations" { - description = "List of objects containing information about the endpoint service private DNS name configuration." - value = aws_vpc_endpoint_service.this.private_dns_name_configuration -} - -output "notification_configurations" { - description = "A list of Endpoint Connection Notifications for VPC Endpoint events." - value = var.notification_configurations -} diff --git a/modules/vpc-endpoint-service/resource-group.tf b/modules/vpc-endpoint-service/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-endpoint-service/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-endpoint-service/variables.tf b/modules/vpc-endpoint-service/variables.tf deleted file mode 100644 index 65f2bb5..0000000 --- a/modules/vpc-endpoint-service/variables.tf +++ /dev/null @@ -1,78 +0,0 @@ -variable "name" { - description = "Desired name for the VPC Endpoint Service." - type = string -} - -variable "gateway_load_balancer_arns" { - description = "List of Amazon Resource Names of one or more Gateway Load Balancers for the endpoint service." - type = list(string) - default = null -} - -variable "network_load_balancer_arns" { - description = "List of Amazon Resource Names of one or more Network Load Balancers for the endpoint service." - type = list(string) - default = null -} - -variable "private_domain" { - description = "The private domain name for the service." - type = string - default = null -} - -variable "acceptance_required" { - description = "Whether or not VPC endpoint connection requests to the service must be accepted by the service owner." - type = bool - default = false -} - -variable "allowed_principals" { - description = "A list of the ARNs of principal to allow to discover a VPC endpoint service." - type = list(string) - default = [] -} - -variable "notification_configurations" { - description = "A list of configurations of Endpoint Connection Notifications for VPC Endpoint events." - type = list(object({ - sns_arn = string - events = list(string) - })) - default = [] -} - -variable "tags" { - description = "A map of tags to add to all resources." - type = map(string) - default = {} -} - -variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." - type = bool - default = true -} - - -################################################### -# Resource Group -################################################### - -variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." - type = bool - default = true -} - -variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." - type = string - default = "" -} - -variable "resource_group_description" { - description = "The description of Resource Group." - type = string - default = "Managed by Terraform." -} diff --git a/modules/vpc-gateway-endpoint/README.md b/modules/vpc-gateway-endpoint/README.md deleted file mode 100644 index a332f96..0000000 --- a/modules/vpc-gateway-endpoint/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# vpc-gateway-endpoint - -This module creates following resources. - -- `aws_vpc_endpoint` -- `aws_vpc_endpoint_connection_notification` (optional) - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.50.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | -| [aws_vpc_endpoint_connection_notification.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint_connection_notification) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [name](#input\_name) | (Required) Desired name for the VPC Gateway Endpoint. | `string` | n/a | yes | -| [service\_name](#input\_service\_name) | (Required) The service name. For AWS services the service name is usually in the form `com.amazonaws..`. | `string` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC in which the endpoint will be used. | `string` | n/a | yes | -| [auto\_accept](#input\_auto\_accept) | (Optional) Accept the VPC endpoint (the VPC endpoint and service need to be in the same AWS account). | `bool` | `true` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [notification\_configurations](#input\_notification\_configurations) | (Optional) A list of configurations of Endpoint Connection Notifications for VPC Endpoint events. |
list(object({
sns_arn = string
events = list(string)
}))
| `[]` | no | -| [policy](#input\_policy) | (Optional) A policy to attach to the endpoint that controls access to the service. This is a JSON formatted string. Defaults to full access. All Gateway and some Interface endpoints support policies. | `string` | `null` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [arn](#output\_arn) | The Amazon Resource Name (ARN) of the VPC endpoint. | -| [cidr\_blocks](#output\_cidr\_blocks) | The list of CIDR blocks for the exposed AWS service. | -| [id](#output\_id) | The ID of the VPC endpoint. | -| [managed](#output\_managed) | Whether or not the VPC Endpoint is being managed by its service. | -| [name](#output\_name) | The VPC Gateway Endpoint name. | -| [notification\_configurations](#output\_notification\_configurations) | A list of Endpoint Connection Notifications for VPC Endpoint events. | -| [owner\_id](#output\_owner\_id) | The Owner ID of the VPC endpoint. | -| [policy](#output\_policy) | The policy which is attached to the endpoint that controls access to the service. | -| [prefix\_list\_id](#output\_prefix\_list\_id) | The prefix list ID of the exposed AWS service. | -| [service\_name](#output\_service\_name) | The service name of the VPC Gateway Endpoint. | -| [state](#output\_state) | The state of the VPC endpoint. | -| [vpc\_id](#output\_vpc\_id) | The VPC ID of the VPC endpoint. | - diff --git a/modules/vpc-gateway-endpoint/main.tf b/modules/vpc-gateway-endpoint/main.tf deleted file mode 100644 index 3ef7380..0000000 --- a/modules/vpc-gateway-endpoint/main.tf +++ /dev/null @@ -1,49 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -resource "aws_vpc_endpoint" "this" { - vpc_endpoint_type = "Gateway" - service_name = var.service_name - vpc_id = var.vpc_id - - auto_accept = var.auto_accept - policy = var.policy - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - - -################################################### -# Notification -################################################### - -resource "aws_vpc_endpoint_connection_notification" "this" { - for_each = { - for config in try(var.notification_configurations, []) : - config.sns_arn => config - } - - vpc_endpoint_id = aws_vpc_endpoint.this.id - - connection_notification_arn = each.key - connection_events = try(each.value.events, []) -} diff --git a/modules/vpc-gateway-endpoint/outputs.tf b/modules/vpc-gateway-endpoint/outputs.tf deleted file mode 100644 index b7b083b..0000000 --- a/modules/vpc-gateway-endpoint/outputs.tf +++ /dev/null @@ -1,59 +0,0 @@ -output "name" { - description = "The VPC Gateway Endpoint name." - value = var.name -} - -output "service_name" { - description = "The service name of the VPC Gateway Endpoint." - value = aws_vpc_endpoint.this.service_name -} - -output "id" { - description = "The ID of the VPC endpoint." - value = aws_vpc_endpoint.this.id -} - -output "arn" { - description = "The Amazon Resource Name (ARN) of the VPC endpoint." - value = aws_vpc_endpoint.this.arn -} - -output "state" { - description = "The state of the VPC endpoint." - value = aws_vpc_endpoint.this.state -} - -output "owner_id" { - description = "The Owner ID of the VPC endpoint." - value = aws_vpc_endpoint.this.owner_id -} - -output "managed" { - description = "Whether or not the VPC Endpoint is being managed by its service." - value = aws_vpc_endpoint.this.requester_managed -} - -output "vpc_id" { - description = "The VPC ID of the VPC endpoint." - value = aws_vpc_endpoint.this.vpc_id -} - -output "cidr_blocks" { - description = "The list of CIDR blocks for the exposed AWS service." - value = aws_vpc_endpoint.this.cidr_blocks -} - -output "prefix_list_id" { - description = "The prefix list ID of the exposed AWS service." - value = aws_vpc_endpoint.this.prefix_list_id -} - -output "policy" { - description = "The policy which is attached to the endpoint that controls access to the service." - value = aws_vpc_endpoint.this.policy -} - -output "notification_configurations" { - description = "A list of Endpoint Connection Notifications for VPC Endpoint events." - value = var.notification_configurations -} diff --git a/modules/vpc-gateway-endpoint/resource-group.tf b/modules/vpc-gateway-endpoint/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-gateway-endpoint/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-gateway-endpoint/variables.tf b/modules/vpc-gateway-endpoint/variables.tf deleted file mode 100644 index 7457b55..0000000 --- a/modules/vpc-gateway-endpoint/variables.tf +++ /dev/null @@ -1,70 +0,0 @@ -variable "name" { - description = "(Required) Desired name for the VPC Gateway Endpoint." - type = string -} - -variable "service_name" { - description = "(Required) The service name. For AWS services the service name is usually in the form `com.amazonaws..`." - type = string -} - -variable "vpc_id" { - description = "(Required) The ID of the VPC in which the endpoint will be used." - type = string -} - -variable "auto_accept" { - description = "(Optional) Accept the VPC endpoint (the VPC endpoint and service need to be in the same AWS account)." - type = bool - default = true -} - -variable "policy" { - description = "(Optional) A policy to attach to the endpoint that controls access to the service. This is a JSON formatted string. Defaults to full access. All Gateway and some Interface endpoints support policies." - type = string - default = null -} - -variable "notification_configurations" { - description = "(Optional) A list of configurations of Endpoint Connection Notifications for VPC Endpoint events." - type = list(object({ - sns_arn = string - events = list(string) - })) - default = [] -} - -variable "tags" { - description = "(Optional) A map of tags to add to all resources." - type = map(string) - default = {} -} - -variable "module_tags_enabled" { - description = "(Optional) Whether to create AWS Resource Tags for the module informations." - type = bool - default = true -} - - -################################################### -# Resource Group -################################################### - -variable "resource_group_enabled" { - description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." - type = bool - default = true -} - -variable "resource_group_name" { - description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." - type = string - default = "" -} - -variable "resource_group_description" { - description = "(Optional) The description of Resource Group." - type = string - default = "Managed by Terraform." -} diff --git a/modules/vpc-interface-endpoint/README.md b/modules/vpc-interface-endpoint/README.md deleted file mode 100644 index 416b817..0000000 --- a/modules/vpc-interface-endpoint/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# vpc-interface-endpoint - -This module creates following resources. - -- `aws_vpc_endpoint` -- `aws_vpc_endpoint_connection_notification` (optional) - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.50.0 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [security\_group](#module\_security\_group) | ../security-group | n/a | - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | -| [aws_vpc_endpoint_connection_notification.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint_connection_notification) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [name](#input\_name) | (Required) Desired name for the VPC Interface Endpoint. | `string` | n/a | yes | -| [service\_name](#input\_service\_name) | (Required) The service name. For AWS services the service name is usually in the form `com.amazonaws..`. | `string` | n/a | yes | -| [subnets](#input\_subnets) | (Required) The ID of one or more subnets in which to create a network interface for the endpoint. | `list(string)` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC in which the endpoint will be used. | `string` | n/a | yes | -| [auto\_accept](#input\_auto\_accept) | (Optional) Accept the VPC endpoint (the VPC endpoint and service need to be in the same AWS account). | `bool` | `true` | no | -| [default\_security\_group](#input\_default\_security\_group) | (Optional) The configuration of the default security group for the interface endpoint. `default_security_group` block as defined below.
(Optional) `name` - The name of the default security group.
(Optional) `description` - The description of the default security group.
(Optional) `ingress_cidrs` - A list of IPv4 CIDR blocks to allow inbound traffic from.
(Optional) `ingress_ipv6_cidrs` - A list of IPv6 CIDR blocks to allow inbound traffic from.
(Optional) `ingress_prefix_lists` - A list of Prefix List IDs to allow inbound traffic from.
(Optional) `ingress_security_groups` - A list of source Security Group IDs to allow inbound traffic from. | `any` | `{}` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [notification\_configurations](#input\_notification\_configurations) | (Optional) A list of configurations of Endpoint Connection Notifications for VPC Endpoint events. |
list(object({
sns_arn = string
events = list(string)
}))
| `[]` | no | -| [policy](#input\_policy) | (Optional) A policy to attach to the endpoint that controls access to the service. This is a JSON formatted string. Defaults to full access. All Gateway and some Interface endpoints support policies. | `string` | `null` | no | -| [private\_dns\_enabled](#input\_private\_dns\_enabled) | (Optional) Whether or not to associate a private hosted zone with the specified VPC. | `bool` | `false` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [security\_groups](#input\_security\_groups) | (Optional) A set of security group IDs to associate with the network interface. | `set(string)` | `[]` | no | -| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [arn](#output\_arn) | The Amazon Resource Name (ARN) of the VPC endpoint. | -| [default\_security\_group](#output\_default\_security\_group) | The default security group of the VPC endpoint. | -| [dns\_configurations](#output\_dns\_configurations) | The DNS entries for the VPC Endpoint. | -| [id](#output\_id) | The ID of the VPC endpoint. | -| [managed](#output\_managed) | Whether or not the VPC Endpoint is being managed by its service. | -| [name](#output\_name) | The VPC Interface Endpoint name. | -| [network\_interface\_ids](#output\_network\_interface\_ids) | One or more network interfaces for the VPC Endpoint. | -| [notification\_configurations](#output\_notification\_configurations) | A list of Endpoint Connection Notifications for VPC Endpoint events. | -| [owner\_id](#output\_owner\_id) | The Owner ID of the VPC endpoint. | -| [policy](#output\_policy) | The policy which is attached to the endpoint that controls access to the service. | -| [security\_groups](#output\_security\_groups) | A set of security group IDs which is assigned to the VPC endpoint. | -| [service\_name](#output\_service\_name) | The service name of the VPC Interface Endpoint. | -| [state](#output\_state) | The state of the VPC endpoint. | -| [subnet\_ids](#output\_subnet\_ids) | A list of Subnet IDs of the VPC endpoint. | -| [vpc\_id](#output\_vpc\_id) | The VPC ID of the VPC endpoint. | - diff --git a/modules/vpc-interface-endpoint/main.tf b/modules/vpc-interface-endpoint/main.tf deleted file mode 100644 index 901d4aa..0000000 --- a/modules/vpc-interface-endpoint/main.tf +++ /dev/null @@ -1,55 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -resource "aws_vpc_endpoint" "this" { - vpc_endpoint_type = "Interface" - service_name = var.service_name - vpc_id = var.vpc_id - subnet_ids = var.subnets - security_group_ids = setunion( - [module.security_group.id], - var.security_groups, - ) - - private_dns_enabled = var.private_dns_enabled - auto_accept = var.auto_accept - policy = var.policy - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - - -################################################### -# Notification -################################################### - -resource "aws_vpc_endpoint_connection_notification" "this" { - for_each = { - for config in try(var.notification_configurations, []) : - config.sns_arn => config - } - - vpc_endpoint_id = aws_vpc_endpoint.this.id - - connection_notification_arn = each.key - connection_events = try(each.value.events, []) -} diff --git a/modules/vpc-interface-endpoint/outputs.tf b/modules/vpc-interface-endpoint/outputs.tf deleted file mode 100644 index cdd8541..0000000 --- a/modules/vpc-interface-endpoint/outputs.tf +++ /dev/null @@ -1,82 +0,0 @@ -output "name" { - description = "The VPC Interface Endpoint name." - value = var.name -} - -output "service_name" { - description = "The service name of the VPC Interface Endpoint." - value = aws_vpc_endpoint.this.service_name -} - -output "id" { - description = "The ID of the VPC endpoint." - value = aws_vpc_endpoint.this.id -} - -output "arn" { - description = "The Amazon Resource Name (ARN) of the VPC endpoint." - value = aws_vpc_endpoint.this.arn -} - -output "state" { - description = "The state of the VPC endpoint." - value = aws_vpc_endpoint.this.state -} - -output "owner_id" { - description = "The Owner ID of the VPC endpoint." - value = aws_vpc_endpoint.this.owner_id -} - -output "managed" { - description = "Whether or not the VPC Endpoint is being managed by its service." - value = aws_vpc_endpoint.this.requester_managed -} - -output "vpc_id" { - description = "The VPC ID of the VPC endpoint." - value = aws_vpc_endpoint.this.vpc_id -} - -output "subnet_ids" { - description = "A list of Subnet IDs of the VPC endpoint." - value = var.subnets -} - -output "default_security_group" { - description = "The default security group of the VPC endpoint." - value = { - id = module.security_group.id - name = module.security_group.name - - ingress_cidrs = try(var.default_security_group.ingress_cidrs, []) - ingress_ipv6_cidrs = try(var.default_security_group.ingress_ipv6_cidrs, []) - ingress_prefix_lists = try(var.default_security_group.ingress_prefix_lists, []) - ingress_security_groups = try(var.default_security_group.ingress_security_groups, []) - } -} - -output "security_groups" { - description = "A set of security group IDs which is assigned to the VPC endpoint." - value = aws_vpc_endpoint.this.security_group_ids -} - -output "network_interface_ids" { - description = "One or more network interfaces for the VPC Endpoint." - value = aws_vpc_endpoint.this.network_interface_ids -} - -output "dns_configurations" { - description = "The DNS entries for the VPC Endpoint." - value = aws_vpc_endpoint.this.dns_entry -} - -output "policy" { - description = "The policy which is attached to the endpoint that controls access to the service." - value = aws_vpc_endpoint.this.policy -} - -output "notification_configurations" { - description = "A list of Endpoint Connection Notifications for VPC Endpoint events." - value = var.notification_configurations -} diff --git a/modules/vpc-interface-endpoint/resource-group.tf b/modules/vpc-interface-endpoint/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-interface-endpoint/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-interface-endpoint/security-group.tf b/modules/vpc-interface-endpoint/security-group.tf deleted file mode 100644 index 94f040d..0000000 --- a/modules/vpc-interface-endpoint/security-group.tf +++ /dev/null @@ -1,72 +0,0 @@ -################################################### -# Security Group for Interface Endpoint -################################################### - -module "security_group" { - source = "../security-group" - - vpc_id = var.vpc_id - - name = try(var.default_security_group.name, local.metadata.name) - description = try(var.default_security_group.description, "Managed by Terraform.") - - ingress_rules = concat( - (length(try(var.default_security_group.ingress_cidrs, [])) > 0 - ? [{ - id = "ipv4-cidrs" - description = "Allow inbound traffic from the IPv4 CIDRs." - protocol = "tcp" - from_port = 0 - to_port = 65535 - - cidr_blocks = try(var.default_security_group.ingress_cidrs, []) - }] - : [] - ), - (length(try(var.default_security_group.ingress_ipv6_cidrs, [])) > 0 - ? [{ - id = "ipv6-cidrs" - description = "Allow inbound traffic from the IPv6 CIDRs." - protocol = "tcp" - from_port = 0 - to_port = 65535 - - ipv6_cidr_blocks = try(var.default_security_group.ingress_ipv6_cidrs, []) - }] - : [] - ), - (length(try(var.default_security_group.ingress_prefix_lists, [])) > 0 - ? [{ - id = "prefix-lists" - description = "Allow inbound traffic from the Prefix Lists." - protocol = "tcp" - from_port = 0 - to_port = 65535 - - prefix_list_ids = try(var.default_security_group.ingress_prefix_lists, []) - }] - : [] - ), - [ - for security_group in try(var.default_security_group.ingress_security_groups, []) : { - id = "security-groups" - description = "Allow inbound traffic from the source Security Groups." - protocol = "tcp" - from_port = 0 - to_port = 65535 - - source_security_group_id = security_group - } - ] - ) - egress_rules = [] - - revoke_rules_on_delete = true - resource_group_enabled = false - module_tags_enabled = false - - tags = merge( - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-interface-endpoint/variables.tf b/modules/vpc-interface-endpoint/variables.tf deleted file mode 100644 index fba3213..0000000 --- a/modules/vpc-interface-endpoint/variables.tf +++ /dev/null @@ -1,101 +0,0 @@ -variable "name" { - description = "(Required) Desired name for the VPC Interface Endpoint." - type = string -} - -variable "service_name" { - description = "(Required) The service name. For AWS services the service name is usually in the form `com.amazonaws..`." - type = string -} - -variable "vpc_id" { - description = "(Required) The ID of the VPC in which the endpoint will be used." - type = string -} - -variable "subnets" { - description = "(Required) The ID of one or more subnets in which to create a network interface for the endpoint." - type = list(string) -} - -variable "private_dns_enabled" { - description = "(Optional) Whether or not to associate a private hosted zone with the specified VPC." - type = bool - default = false -} - -variable "default_security_group" { - description = < -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.45.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_peering_connection_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection_accepter) | resource | -| [aws_vpc_peering_connection_options.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection_options) | resource | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | -| [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc_peering_connection) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [id](#input\_id) | The VPC Peering Connection ID to manage. | `string` | n/a | yes | -| [allow\_remote\_vpc\_dns\_resolution](#input\_allow\_remote\_vpc\_dns\_resolution) | Allow a accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. This is not supported for inter-region VPC peering. | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [name](#input\_name) | Desired name for the VPC Peering resources. | `string` | `""` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [accepter](#output\_accepter) | The accepter information including AWS Account ID, Region, VPC ID. | -| [id](#output\_id) | The ID of the VPC Peering Connection. | -| [name](#output\_name) | The VPC Peering name. | -| [requester](#output\_requester) | The requester information including AWS Account ID, Region, VPC ID. | -| [status](#output\_status) | The status of the VPC Peering Connection request. | - diff --git a/modules/vpc-peering-accepter/main.tf b/modules/vpc-peering-accepter/main.tf deleted file mode 100644 index c089426..0000000 --- a/modules/vpc-peering-accepter/main.tf +++ /dev/null @@ -1,73 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -data "aws_caller_identity" "this" {} -data "aws_region" "this" {} - -locals { - requester = { - account_id = aws_vpc_peering_connection_accepter.this.peer_owner_id - region = aws_vpc_peering_connection_accepter.this.peer_region - vpc_id = aws_vpc_peering_connection_accepter.this.peer_vpc_id - cidr_block = data.aws_vpc_peering_connection.this.cidr_block - secondary_cidr_blocks = [ - for cidr in data.aws_vpc_peering_connection.this.cidr_block_set : - cidr.cidr_block - if cidr.cidr_block != data.aws_vpc_peering_connection.this.cidr_block - ] - } - accepter = { - account_id = data.aws_caller_identity.this.account_id - region = data.aws_region.this.name - vpc_id = aws_vpc_peering_connection_accepter.this.vpc_id - cidr_block = data.aws_vpc_peering_connection.this.peer_cidr_block - secondary_cidr_blocks = [ - for cidr in data.aws_vpc_peering_connection.this.peer_cidr_block_set : - cidr.cidr_block - if cidr.cidr_block != data.aws_vpc_peering_connection.this.peer_cidr_block - ] - } -} - - -################################################### -# VPC Peering for Accepter -################################################### - -resource "aws_vpc_peering_connection_accepter" "this" { - vpc_peering_connection_id = var.id - auto_accept = true - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - -resource "aws_vpc_peering_connection_options" "this" { - vpc_peering_connection_id = aws_vpc_peering_connection_accepter.this.id - - accepter { - allow_remote_vpc_dns_resolution = var.allow_remote_vpc_dns_resolution - } -} - -data "aws_vpc_peering_connection" "this" { - id = aws_vpc_peering_connection_accepter.this.id -} diff --git a/modules/vpc-peering-accepter/outputs.tf b/modules/vpc-peering-accepter/outputs.tf deleted file mode 100644 index faaa1cb..0000000 --- a/modules/vpc-peering-accepter/outputs.tf +++ /dev/null @@ -1,24 +0,0 @@ -output "name" { - description = "The VPC Peering name." - value = var.name -} - -output "id" { - description = "The ID of the VPC Peering Connection." - value = aws_vpc_peering_connection_accepter.this.id -} - -output "status" { - description = "The status of the VPC Peering Connection request." - value = aws_vpc_peering_connection_accepter.this.accept_status -} - -output "requester" { - description = "The requester information including AWS Account ID, Region, VPC ID." - value = local.requester -} - -output "accepter" { - description = "The accepter information including AWS Account ID, Region, VPC ID." - value = local.accepter -} diff --git a/modules/vpc-peering-accepter/resource-group.tf b/modules/vpc-peering-accepter/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-peering-accepter/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-peering-accepter/variables.tf b/modules/vpc-peering-accepter/variables.tf deleted file mode 100644 index 308a0d6..0000000 --- a/modules/vpc-peering-accepter/variables.tf +++ /dev/null @@ -1,51 +0,0 @@ -variable "id" { - description = "The VPC Peering Connection ID to manage." - type = string -} - -variable "name" { - description = "Desired name for the VPC Peering resources." - type = string - default = "" -} - -variable "allow_remote_vpc_dns_resolution" { - description = "Allow a accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. This is not supported for inter-region VPC peering." - type = bool - default = false -} - -variable "tags" { - description = "A map of tags to add to all resources." - type = map(string) - default = {} -} - -variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." - type = bool - default = true -} - - -################################################### -# Resource Group -################################################### - -variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." - type = bool - default = true -} - -variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." - type = string - default = "" -} - -variable "resource_group_description" { - description = "The description of Resource Group." - type = string - default = "Managed by Terraform." -} diff --git a/modules/vpc-peering-accepter/versions.tf b/modules/vpc-peering-accepter/versions.tf deleted file mode 100644 index 6078ceb..0000000 --- a/modules/vpc-peering-accepter/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 0.15" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 3.45" - } - } -} diff --git a/modules/vpc-peering-requester/README.md b/modules/vpc-peering-requester/README.md deleted file mode 100644 index e56c9bf..0000000 --- a/modules/vpc-peering-requester/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# vpc-peering-requester - -This module creates following resources. - -- `aws_vpc_peering_connection` -- `aws_vpc_peering_connection_options` (optional) - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.45.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection) | resource | -| [aws_vpc_peering_connection_options.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection_options) | resource | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | -| [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc_peering_connection) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [accepter\_vpc\_id](#input\_accepter\_vpc\_id) | The ID of the VPC with which you are creating the VPC Peering Connection. | `string` | n/a | yes | -| [name](#input\_name) | Desired name for the VPC Peering resources. | `string` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | The ID of the requester VPC. | `string` | n/a | yes | -| [accepter\_account\_id](#input\_accepter\_account\_id) | The AWS account ID of the owner of the peer VPC. | `string` | `null` | no | -| [accepter\_region](#input\_accepter\_region) | The region of the VPC with which you are creating the VPC Peering Connection. | `string` | `null` | no | -| [allow\_remote\_vpc\_dns\_resolution](#input\_allow\_remote\_vpc\_dns\_resolution) | Allow a requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC. This is not supported for inter-region VPC peering. | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [accepter](#output\_accepter) | The accepter information including AWS Account ID, Region, VPC ID. | -| [id](#output\_id) | The ID of the VPC Peering Connection. | -| [name](#output\_name) | The VPC Peering name. | -| [requester](#output\_requester) | The requester information including AWS Account ID, Region, VPC ID. | -| [status](#output\_status) | The status of the VPC Peering Connection request. | - diff --git a/modules/vpc-peering-requester/main.tf b/modules/vpc-peering-requester/main.tf deleted file mode 100644 index d6c22b4..0000000 --- a/modules/vpc-peering-requester/main.tf +++ /dev/null @@ -1,67 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -data "aws_caller_identity" "this" {} -data "aws_region" "this" {} - -locals { - requester = { - account_id = data.aws_caller_identity.this.account_id - region = data.aws_region.this.name - vpc_id = var.vpc_id - } - accepter = { - account_id = var.accepter_account_id != null ? var.accepter_account_id : local.requester.account_id - region = var.accepter_region != null ? var.accepter_region : local.requester.region - vpc_id = var.accepter_vpc_id - } -} - - -################################################### -# VPC Peering for Requester -################################################### - -resource "aws_vpc_peering_connection" "this" { - vpc_id = local.requester.vpc_id - auto_accept = false - - peer_vpc_id = local.accepter.vpc_id - peer_region = local.accepter.region - peer_owner_id = local.accepter.account_id - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - -resource "aws_vpc_peering_connection_options" "this" { - count = var.allow_remote_vpc_dns_resolution ? 1 : 0 - - vpc_peering_connection_id = aws_vpc_peering_connection.this.id - - requester { - allow_remote_vpc_dns_resolution = true - } -} - -data "aws_vpc_peering_connection" "this" { - id = aws_vpc_peering_connection.this.id -} diff --git a/modules/vpc-peering-requester/outputs.tf b/modules/vpc-peering-requester/outputs.tf deleted file mode 100644 index 70113c6..0000000 --- a/modules/vpc-peering-requester/outputs.tf +++ /dev/null @@ -1,38 +0,0 @@ -output "name" { - description = "The VPC Peering name." - value = var.name -} - -output "id" { - description = "The ID of the VPC Peering Connection." - value = aws_vpc_peering_connection.this.id -} - -output "status" { - description = "The status of the VPC Peering Connection request." - value = aws_vpc_peering_connection.this.accept_status -} - -output "requester" { - description = "The requester information including AWS Account ID, Region, VPC ID." - value = merge(local.requester, { - cidr_block = data.aws_vpc_peering_connection.this.cidr_block - secondary_cidr_blocks = [ - for cidr in data.aws_vpc_peering_connection.this.cidr_block_set : - cidr.cidr_block - if cidr.cidr_block != data.aws_vpc_peering_connection.this.cidr_block - ] - }) -} - -output "accepter" { - description = "The accepter information including AWS Account ID, Region, VPC ID." - value = merge(local.accepter, { - cidr_block = data.aws_vpc_peering_connection.this.peer_cidr_block - secondary_cidr_blocks = [ - for cidr in data.aws_vpc_peering_connection.this.peer_cidr_block_set : - cidr.cidr_block - if cidr.cidr_block != data.aws_vpc_peering_connection.this.peer_cidr_block - ] - }) -} diff --git a/modules/vpc-peering-requester/resource-group.tf b/modules/vpc-peering-requester/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-peering-requester/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-peering-requester/variables.tf b/modules/vpc-peering-requester/variables.tf deleted file mode 100644 index 3c3a561..0000000 --- a/modules/vpc-peering-requester/variables.tf +++ /dev/null @@ -1,67 +0,0 @@ -variable "name" { - description = "Desired name for the VPC Peering resources." - type = string -} - -variable "vpc_id" { - description = "The ID of the requester VPC." - type = string -} - -variable "accepter_vpc_id" { - description = "The ID of the VPC with which you are creating the VPC Peering Connection." - type = string -} - -variable "accepter_region" { - description = "The region of the VPC with which you are creating the VPC Peering Connection." - type = string - default = null -} - -variable "accepter_account_id" { - description = "The AWS account ID of the owner of the peer VPC." - type = string - default = null -} - -variable "allow_remote_vpc_dns_resolution" { - description = "Allow a requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC. This is not supported for inter-region VPC peering." - type = bool - default = false -} - -variable "tags" { - description = "A map of tags to add to all resources." - type = map(string) - default = {} -} - -variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." - type = bool - default = true -} - - -################################################### -# Resource Group -################################################### - -variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." - type = bool - default = true -} - -variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." - type = string - default = "" -} - -variable "resource_group_description" { - description = "The description of Resource Group." - type = string - default = "Managed by Terraform." -} diff --git a/modules/vpc-peering-requester/versions.tf b/modules/vpc-peering-requester/versions.tf deleted file mode 100644 index 6078ceb..0000000 --- a/modules/vpc-peering-requester/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 0.15" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 3.45" - } - } -} diff --git a/modules/vpc-peering/README.md b/modules/vpc-peering/README.md deleted file mode 100644 index 9a7f528..0000000 --- a/modules/vpc-peering/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# vpc-peering - -This module creates following resources. - -- `aws_vpc_peering_connection` - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.45.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | -| [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection) | resource | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | -| [aws_vpc.accepter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | -| [aws_vpc.requester](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [accepter\_vpc\_id](#input\_accepter\_vpc\_id) | The ID of the VPC with which you are creating the VPC Peering Connection. | `string` | n/a | yes | -| [name](#input\_name) | Desired name for the VPC Peering resources. | `string` | n/a | yes | -| [requester\_vpc\_id](#input\_requester\_vpc\_id) | The ID of the requester VPC. | `string` | n/a | yes | -| [accepter\_allow\_remote\_vpc\_dns\_resolution](#input\_accepter\_allow\_remote\_vpc\_dns\_resolution) | Allow a accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. This is not supported for inter-region VPC peering. | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [requester\_allow\_remote\_vpc\_dns\_resolution](#input\_requester\_allow\_remote\_vpc\_dns\_resolution) | Allow a requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC. This is not supported for inter-region VPC peering. | `bool` | `false` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [accepter](#output\_accepter) | The accepter information including AWS Account ID, Region, VPC ID. | -| [id](#output\_id) | The ID of the VPC Peering Connection. | -| [name](#output\_name) | The VPC Peering name. | -| [requester](#output\_requester) | The requester information including AWS Account ID, Region, VPC ID. | -| [status](#output\_status) | The status of the VPC Peering Connection request. | - diff --git a/modules/vpc-peering/main.tf b/modules/vpc-peering/main.tf deleted file mode 100644 index 770aa5c..0000000 --- a/modules/vpc-peering/main.tf +++ /dev/null @@ -1,78 +0,0 @@ -locals { - metadata = { - package = "terraform-aws-network" - version = trimspace(file("${path.module}/../../VERSION")) - module = basename(path.module) - name = var.name - } - module_tags = var.module_tags_enabled ? { - "module.terraform.io/package" = local.metadata.package - "module.terraform.io/version" = local.metadata.version - "module.terraform.io/name" = local.metadata.module - "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" - "module.terraform.io/instance" = local.metadata.name - } : {} -} - -data "aws_caller_identity" "this" {} -data "aws_region" "this" {} - -data "aws_vpc" "requester" { - id = var.requester_vpc_id -} - -data "aws_vpc" "accepter" { - id = var.accepter_vpc_id -} - -locals { - requester = { - account_id = data.aws_caller_identity.this.account_id - region = data.aws_region.this.name - vpc_id = var.requester_vpc_id - cidr_block = data.aws_vpc.requester.cidr_block - secondary_cidr_blocks = [ - for association in data.aws_vpc.requester.cidr_block_associations : - association.cidr_block - if association.cidr_block != data.aws_vpc.requester.cidr_block - ] - } - accepter = { - account_id = data.aws_caller_identity.this.account_id - region = data.aws_region.this.name - vpc_id = var.accepter_vpc_id - cidr_block = data.aws_vpc.accepter.cidr_block - secondary_cidr_blocks = [ - for association in data.aws_vpc.accepter.cidr_block_associations : - association.cidr_block - if association.cidr_block != data.aws_vpc.accepter.cidr_block - ] - } -} - - -################################################### -# VPC Peering -################################################### - -resource "aws_vpc_peering_connection" "this" { - vpc_id = local.requester.vpc_id - peer_vpc_id = local.accepter.vpc_id - auto_accept = true - - requester { - allow_remote_vpc_dns_resolution = var.requester_allow_remote_vpc_dns_resolution - } - - accepter { - allow_remote_vpc_dns_resolution = var.accepter_allow_remote_vpc_dns_resolution - } - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-peering/outputs.tf b/modules/vpc-peering/outputs.tf deleted file mode 100644 index 82f47eb..0000000 --- a/modules/vpc-peering/outputs.tf +++ /dev/null @@ -1,24 +0,0 @@ -output "name" { - description = "The VPC Peering name." - value = var.name -} - -output "id" { - description = "The ID of the VPC Peering Connection." - value = aws_vpc_peering_connection.this.id -} - -output "status" { - description = "The status of the VPC Peering Connection request." - value = aws_vpc_peering_connection.this.accept_status -} - -output "requester" { - description = "The requester information including AWS Account ID, Region, VPC ID." - value = local.requester -} - -output "accepter" { - description = "The accepter information including AWS Account ID, Region, VPC ID." - value = local.accepter -} diff --git a/modules/vpc-peering/resource-group.tf b/modules/vpc-peering/resource-group.tf deleted file mode 100644 index af108f9..0000000 --- a/modules/vpc-peering/resource-group.tf +++ /dev/null @@ -1,44 +0,0 @@ -locals { - resource_group_name = (var.resource_group_name != "" - ? var.resource_group_name - : join(".", [ - local.metadata.package, - local.metadata.module, - replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), - ]) - ) - resource_group_filters = [ - for key, value in local.module_tags : { - "Key" = key - "Values" = [value] - } - ] - resource_group_query = <<-JSON - { - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": ${jsonencode(local.resource_group_filters)} - } - JSON -} - -resource "aws_resourcegroups_group" "this" { - count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 - - name = local.resource_group_name - description = var.resource_group_description - - resource_query { - type = "TAG_FILTERS_1_0" - query = local.resource_group_query - } - - tags = merge( - { - "Name" = local.resource_group_name - }, - local.module_tags, - var.tags, - ) -} diff --git a/modules/vpc-peering/variables.tf b/modules/vpc-peering/variables.tf deleted file mode 100644 index 8fe1edd..0000000 --- a/modules/vpc-peering/variables.tf +++ /dev/null @@ -1,61 +0,0 @@ -variable "name" { - description = "Desired name for the VPC Peering resources." - type = string -} - -variable "requester_vpc_id" { - description = "The ID of the requester VPC." - type = string -} - -variable "accepter_vpc_id" { - description = "The ID of the VPC with which you are creating the VPC Peering Connection." - type = string -} - -variable "requester_allow_remote_vpc_dns_resolution" { - description = "Allow a requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC. This is not supported for inter-region VPC peering." - type = bool - default = false -} - -variable "accepter_allow_remote_vpc_dns_resolution" { - description = "Allow a accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. This is not supported for inter-region VPC peering." - type = bool - default = false -} - -variable "tags" { - description = "A map of tags to add to all resources." - type = map(string) - default = {} -} - -variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." - type = bool - default = true -} - - -################################################### -# Resource Group -################################################### - -variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." - type = bool - default = true -} - -variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." - type = string - default = "" -} - -variable "resource_group_description" { - description = "The description of Resource Group." - type = string - default = "Managed by Terraform." -} diff --git a/modules/vpc-peering/versions.tf b/modules/vpc-peering/versions.tf deleted file mode 100644 index 6078ceb..0000000 --- a/modules/vpc-peering/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 0.15" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 3.45" - } - } -} diff --git a/modules/vpc/README.md b/modules/vpc/README.md index 7655075..02cbf5d 100644 --- a/modules/vpc/README.md +++ b/modules/vpc/README.md @@ -3,108 +3,109 @@ This module creates following resources. - `aws_vpc` -- `aws_vpc_ipv4_cidr_block_association` (optional) -- `aws_route53_zone_association` (optional) +- `aws_default_network_acl` +- `aws_default_security_group` - `aws_vpc_dhcp_options` (optional) - `aws_vpc_dhcp_options_association` (optional) +- `aws_vpc_ipv4_cidr_block_association` (optional) +- `aws_vpc_ipv6_cidr_block_association` (optional) +- `aws_route53_zone_association` (optional) - `aws_internet_gateway` (optional) +- `aws_internet_gateway_attachment` (optional) - `aws_egress_only_internet_gateway` (optional) - `aws_vpn_gateway` (optional) +- `aws_vpn_gateway_attachment` (optional) ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | -| [aws](#requirement\_aws) | >= 3.45 | +| [terraform](#requirement\_terraform) | >= 1.6 | +| [aws](#requirement\_aws) | >= 5.3 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 3.45.0 | +| [aws](#provider\_aws) | 5.22.0 | ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | ## Resources | Name | Type | |------|------| +| [aws_default_network_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl) | resource | +| [aws_default_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_security_group) | resource | | [aws_egress_only_internet_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/egress_only_internet_gateway) | resource | | [aws_internet_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | resource | -| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | +| [aws_internet_gateway_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway_attachment) | resource | | [aws_route53_resolver_dnssec_config.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_resolver_dnssec_config) | resource | | [aws_route53_zone_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone_association) | resource | | [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | resource | | [aws_vpc_dhcp_options.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_dhcp_options) | resource | | [aws_vpc_dhcp_options_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_dhcp_options_association) | resource | | [aws_vpc_ipv4_cidr_block_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv4_cidr_block_association) | resource | +| [aws_vpc_ipv6_cidr_block_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv6_cidr_block_association) | resource | | [aws_vpn_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway) | resource | -| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_vpn_gateway_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_attachment) | resource | +| [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the VPC resources. | `string` | n/a | yes | -| [cidr\_block](#input\_cidr\_block) | The CIDR block for the VPC. Default value is a valid CIDR, but not acceptable by AWS and should be overridden. | `string` | `"0.0.0.0/0"` | 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\_enabled](#input\_dhcp\_options\_enabled) | Should be true if you want to specify a DHCP options set with a custom domain name, DNS servers, NTP servers, netbios servers, and/or netbios server type. | `bool` | `false` | 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 | -| [dns\_dnssec\_validation\_enabled](#input\_dns\_dnssec\_validation\_enabled) | Should be true to enable Route53 DNSSEC validation in the VPC. | `bool` | `false` | no | -| [dns\_hostnames\_enabled](#input\_dns\_hostnames\_enabled) | Should be true to enable DNS hostnames in the VPC. | `bool` | `false` | no | -| [dns\_support\_enabled](#input\_dns\_support\_enabled) | Should be true to enable DNS support in the VPC. | `bool` | `true` | no | -| [egress\_only\_internet\_gateway\_enabled](#input\_egress\_only\_internet\_gateway\_enabled) | Should be true if you want to create a new Egress Only Internet Gateway resource and attach it to the VPC. | `bool` | `false` | no | -| [instance\_tenancy](#input\_instance\_tenancy) | A tenancy option for instances launched into the VPC. Only support `default` or `dedicated`. | `string` | `"default"` | no | -| [internet\_gateway\_enabled](#input\_internet\_gateway\_enabled) | Should be true if you want to create a new Internet Gateway resource and attach it to the VPC. | `bool` | `true` | no | -| [ipv6\_enabled](#input\_ipv6\_enabled) | Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or the size of the CIDR block. | `bool` | `false` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [private\_hosted\_zones](#input\_private\_hosted\_zones) | List of private Hosted Zone IDs to associate. | `list(string)` | `[]` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [secondary\_cidr\_blocks](#input\_secondary\_cidr\_blocks) | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | -| [vpn\_gateway\_asn](#input\_vpn\_gateway\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | `string` | `"64512"` | no | -| [vpn\_gateway\_enabled](#input\_vpn\_gateway\_enabled) | Should be true if you want to create a new VPN Gateway resource and attach it to the VPC. | `bool` | `false` | no | +| [name](#input\_name) | (Required) Desired name for the VPC resources. | `string` | n/a | yes | +| [default\_network\_acl](#input\_default\_network\_acl) | (Optional) The configuration for the default Network ACL of the VPC. `default_network_acl` as defined below.
(Optional) `name` - The name of the default Network ACL. Defaults to same name of the VPC.
(Optional) `ingress_rules` - A set of ingress rules in the default Network ACL. If not explicitly defined, the AWS default rules are applied. `ingress_rules` as defined below.
(Required) `priority` - The rule priority. The rule number. Used for ordering.
(Required) `action` - The action to indicate whether to allow or deny the traffic that matches the rule. Valid values are `ALLOW` and `DENY`.
(Required) `protocol` - The protocol to match. If using the `-1` 'all' protocol, you must specify a from and to port of `0`.
(Required) `from_port` - The from port to match.
(Required) `to_port` - The to port to match.
(Optional) `ipv4_cidr` - The IPv4 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv6_cidr`.
(Optional) `ipv6_cidr` - The IPv6 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv4_cidr`.
(Optional) `icmp_type` - The ICMP type to be used. Defaults to `0`.
(Optional) `icmp_code` - The ICMP code to be used. Defaults to `0`.
(Optional) `egress_rules` - A set of egress rules in the default Network ACL. If not explicitly defined, the AWS default rules are applied. `egress_rules` as defined below.
(Required) `priority` - The rule priority. The rule number. Used for ordering.
(Required) `action` - The action to indicate whether to allow or deny the traffic that matches the rule. Valid values are `ALLOW` and `DENY`.
(Required) `protocol` - The protocol to match. If using the `-1` 'all' protocol, you must specify a from and to port of `0`.
(Required) `from_port` - The from port to match.
(Required) `to_port` - The to port to match.
(Optional) `ipv4_cidr` - The IPv4 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv6_cidr`.
(Optional) `ipv6_cidr` - The IPv6 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv4_cidr`.
(Optional) `icmp_type` - The ICMP type to be used. Defaults to `0`.
(Optional) `icmp_code` - The ICMP code to be used. Defaults to `0`. |
object({
name = optional(string)
ingress_rules = optional(set(object({
priority = number
action = string
protocol = string
from_port = number
to_port = number
ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
icmp_type = optional(number, 0)
icmp_code = optional(number, 0)
})))
egress_rules = optional(set(object({
priority = number
action = string
protocol = string
from_port = number
to_port = number
ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
icmp_type = optional(number, 0)
icmp_code = optional(number, 0)
})))
})
| `{}` | no | +| [default\_security\_group](#input\_default\_security\_group) | (Optional) The configuration for the default Security Group of the VPC. `default_security_group` as defined below.
(Optional) `name` - The name of the default Security Group. Defaults to same name of the VPC.
(Optional) `ingress_rules` - A set of ingress rules in the default Security Group. If not explicitly defined, the AWS default rules are applied. `ingress_rules` as defined below.
(Optional) `description` - The description of the rule.
(Required) `protocol` - The protocol to match. If using the `-1` 'all' protocol, you must specify a from and to port of `0`.
(Required) `from_port` - The from port to match.
(Required) `to_port` - The to port to match.
(Optional) `ipv4_cidrs` - The IPv4 network ranges to allow, in CIDR notation. Cannot be specified with `ipv6_cidrs`.
(Optional) `ipv6_cidrs` - The IPv6 network ranges to allow, in CIDR notation. Cannot be specified with `ipv4_cidrs`.
(Optional) `prefix_lists` - The prefix list IDs to allow.
(Optional) `security_groups` - The source security group IDs to allow.
(Optional) `self` - Whether the security group itself will be added as a source to this ingress rule.
(Optional) `egress_rules` - A set of egress rules in the default Security Group. If not explicitly defined, the AWS default rules are applied. `egress_rules` as defined below.
(Optional) `description` - The description of the rule.
(Required) `protocol` - The protocol to match. If using the `-1` 'all' protocol, you must specify a from and to port of `0`.
(Required) `from_port` - The from port to match.
(Required) `to_port` - The to port to match.
(Optional) `ipv4_cidrs` - The IPv4 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv6_cidrs`.
(Optional) `ipv6_cidrs` - The IPv6 network range to allow or deny, in CIDR notation. Cannot be specified with `ipv4_cidrs`.
(Optional) `prefix_lists` - The prefix list IDs to allow.
(Optional) `security_groups` - The source security group IDs to allow.
(Optional) `self` - Whether the security group itself will be added as a source to this ingress rule. |
object({
name = optional(string)
ingress_rules = optional(set(object({
description = optional(string, "Managed by Terraform.")
protocol = string
from_port = number
to_port = number
ipv4_cidrs = optional(set(string))
ipv6_cidrs = optional(set(string))
prefix_lists = optional(set(string))
security_groups = optional(set(string))
self = optional(bool, false)
})))
egress_rules = optional(set(object({
description = optional(string, "Managed by Terraform.")
protocol = string
from_port = number
to_port = number
ipv4_cidrs = optional(set(string))
ipv6_cidrs = optional(set(string))
prefix_lists = optional(set(string))
security_groups = optional(set(string))
self = optional(bool, false)
})))
})
| `{}` | no | +| [dhcp\_options](#input\_dhcp\_options) | (Optional) The configuration for a DHCP option set of the VPC. Dynamic Host Configuration Protocol (DHCP) provides a standard for passing configuration information to hosts on a TCP/IP network. `dhcp_options` as defined below.
(Optional) `enabled` - Whether to create a DHCP option set for the VPC. Defaults to `false`.
(Optional) `name` - The name of the DHCP option set. Defaults to same name of the VPC.
(Optional) `domain_name` - The suffix domain name to use by default when resolving non Fully Qualified Domain Names. In other words, this is what ends up being the search value in the `/etc/resolv.conf` file. If you're using `AmazonProvidedDNS` in `us-east-1`, specify `ec2.internal`. If you're using `AmazonProvidedDNS` in another Region, specify `{region}.compute.internal`.
(Optional) `domain_name_servers` - A list of name servers to configure in `/etc/resolv.conf`. The IP addresses of up to four domain name servers, or `AmazonProvidedDNS`. If you want to use the default AWS nameservers you should set this to `AmazonProvidedDNS`. Defaults to `["AmazonProvidedDNS"]`.
(Optional) `netbios_name_servers` - A list of NetBIOS name servers. The IP addresses of up to four NetBIOS name servers.
(Optional) `netbios_node_type` - The NetBIOS node type (1, 2, 4, or 8). AWS recommends to specify 2 since broadcast and multicast are not supported in their network. For more information about these node types, see RFC 2132. Defaults to `2`.
(Optional) `ntp_servers` - A list of NTP servers to configure. The IP addresses of up to four Network Time Protocol (NTP) servers. |
object({
enabled = optional(bool, false)
name = optional(string)
domain_name = optional(string)
domain_name_servers = optional(list(string), ["AmazonProvidedDNS"])
netbios_name_servers = optional(list(string), [])
netbios_node_type = optional(number, 2)
ntp_servers = optional(list(string), [])
})
| `{}` | no | +| [dns\_dnssec\_validation\_enabled](#input\_dns\_dnssec\_validation\_enabled) | (Optional) Should be true to enable Route53 DNSSEC validation in the VPC. | `bool` | `false` | no | +| [dns\_hostnames\_enabled](#input\_dns\_hostnames\_enabled) | (Optional) Whether instances launched in the VPC receive public DNS hostnames that correspond to their public IP addresses. Defaults to `true`. | `bool` | `true` | no | +| [dns\_resolution\_enabled](#input\_dns\_resolution\_enabled) | (Optional) Whether DNS resolution through the Amazon DNS server is supported for the VPC. Defaults to `true`. | `bool` | `true` | no | +| [egress\_only\_internet\_gateway](#input\_egress\_only\_internet\_gateway) | (Required) The configuration for an Egress-only Internet Gateway of the VPC. Egress-only Internet Gateway is VPC component that allows outbound only communication to the internet over IPv6, and prevents the Internet from initiating an IPv6 connection with your instances. `egress_only_internet_gateway` as defined below.
(Optional) `enabled` - Whether to create an egress-only Internet gateway for the VPC. Defaults to `false`.
(Optional) `name` - The name of the Egress-only Internet Gateway. Defaults to same name of the VPC. |
object({
enabled = optional(bool, false)
name = optional(string)
})
| `{}` | no | +| [internet\_gateway](#input\_internet\_gateway) | (Required) The configuration for an Internet Gateway of the VPC. An internet gateway is a virtual router that connects a VPC to the internet. `internet_gateway` as defined below.
(Optional) `enabled` - Whether to create an Internet gateway for the VPC. Defaults to `true`.
(Optional) `name` - The name of the Internet Gateway. Defaults to same name of the VPC. |
object({
enabled = optional(bool, true)
name = optional(string)
})
| `{}` | no | +| [ipv4\_cidrs](#input\_ipv4\_cidrs) | (Required) A list of IPv4 CIDR blocks for the VPC. At least one CIDR must be defined. Each block of `ipv4_cidrs` as defined below.
(Optional) `type` - Valid values are `MANUAL` and `IPAM_POOL`. Defaults to `MANUAL`.
(Optional) `cidr` - The CIDR block for the VPC. CIDR block size must be between /16 and /28.
(Optional) `ipam_pool` - The configuration to get an IPv4 CIDR from the IPAM pool to use for the VPC. Required if `type` is `IPAM_POOL`. `ipam_pool` as defined below.
(Required) `id` - The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR.
(Optional) `netmask_length` - The netmask length of the IPv4 CIDR you want to allocate to this VPC. |
list(object({
type = optional(string, "MANUAL")
cidr = optional(string)
ipam_pool = optional(object({
id = string
netmask_length = optional(number)
}))
}))
| `[]` | no | +| [ipv6\_cidrs](#input\_ipv6\_cidrs) | (Optional) A list of IPv6 CIDR blocks for the VPC. Each block of `ipv6_cidrs` as defined below.
(Optional) `type` - Valid values are `AMAZON` and `IPAM_POOL`. Defaults to `AMAZON`.
(Optional) `amazon` - The configuration to get the Amazon-provided IPv6 CIDR to use for the VPC. Only used if `type` is `AMAZON`. `amazon` as defined below.
(Optional) `network_border_group` - The name of the network border group. This can be changed to restrict advertisement of public addresses to specific Network Border Groups such as LocalZones. Defaults to the region of the VPC.
(Optional) `ipam_pool` - The configuration to get an IPv6 CIDR from the IPAM pool to use for the VPC. Required if `type` is `IPAM_POOL`. `ipam_pool` as defined below.
(Required) `id` - The ID of an IPv6 IPAM pool you want to use for allocating this VPC's CIDR.
(Optional) `cidr` - The CIDR block for the VPC. The CIDR can be explicitly set. Required if `netmask_length` is not set and the IPAM pool does not have `allocation_default_netmask` set.
(Optional) `netmask_length` - The netmask length of the IPv6 CIDR you want to allocate to this VPC. |
list(object({
type = optional(string, "AMAZON")
amazon = optional(object({
network_border_group = optional(string)
}), {})
ipam_pool = optional(object({
id = string
cidr = optional(string)
netmask_length = optional(number)
}))
}))
| `[]` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [network\_address\_usage\_metrics\_enabled](#input\_network\_address\_usage\_metrics\_enabled) | (Optional) Whether NAU (Network Address Usage) metrics are enabled for the VPC. Defaults to `false`. | `bool` | `false` | no | +| [private\_hosted\_zones](#input\_private\_hosted\_zones) | (Optional) List of private Hosted Zone IDs to associate. | `list(string)` | `[]` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [tenancy](#input\_tenancy) | (Optional) A tenancy option for instances launched into the VPC. Valid values are `DEFAULT` and `DEDICATED`. Defaults to `DEFAULT`.
`DEFAULT` - Ensure that EC2 instances launched in this VPC use the EC2 instance tenancy attribute specified when the EC2 instance is launched
`DEDICATED` - Ensure that EC2 instances launched in this VPC are run on dedicated tenancy instances regardless of the tenancy attribute specified at launch. This has a dedicated per region fee of $2 per hour, plus an hourly per instance usage fee. | `string` | `"DEFAULT"` | no | +| [vpn\_gateway](#input\_vpn\_gateway) | (Required) The configuration for a virtual private gateway of the VPC. A virtual private gateway is the VPN concentrator on the Amazon side of the site-to-site VPN connection. `vpn_gateway` as defined below.
(Optional) `enabled` - Whether to create a new VPN Gateway resource and attach it to the VPC. Defaults to `false`.
(Optional) `name` - The name of the VPN Gateway. Defaults to same name of the VPC.
(Optional) `asn` - The Autonomous System Number (ASN) for the Amazon side of the gateway. Defaults to `64512`. |
object({
enabled = optional(bool, false)
name = optional(string)
asn = optional(number, 64512)
})
| `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [arn](#output\_arn) | The ARN of the VPC. | -| [cidr\_block](#output\_cidr\_block) | The CIDR block of the VPC. | -| [default\_network\_acl\_id](#output\_default\_network\_acl\_id) | The ID of the default network ACL. | -| [default\_route\_table\_id](#output\_default\_route\_table\_id) | The ID of the default route table. | -| [default\_security\_group\_id](#output\_default\_security\_group\_id) | The ID of the security group created by default on VPC creation. | -| [dhcp\_options\_arn](#output\_dhcp\_options\_arn) | The ARN of the DHCP Options Set. | -| [dhcp\_options\_enabled](#output\_dhcp\_options\_enabled) | Whether DHCP options set is enabled in the VPC. | -| [dhcp\_options\_id](#output\_dhcp\_options\_id) | The ID of the DHCP Options Set. | +| [arn](#output\_arn) | The ARN (Amazon Resource Name) of the VPC. | +| [default\_network\_acl](#output\_default\_network\_acl) | The configuration for the default Network ACL of the VPC.
`id` - The ID of the default Network ACL.
`arn` - The ARN of the default Network ACL.
`owner` - The ID of the AWS account that owns the default Network ACL. | +| [default\_route\_table](#output\_default\_route\_table) | The configuration for the default Route Table of the VPC.
`id` - The ID of the default Route Table. | +| [default\_security\_group](#output\_default\_security\_group) | The configuration for the default Security Group of the VPC.
`id` - The ID of the default Security Group.
`arn` - The ARN of the default Security Group.
`owner` - The ID of the AWS account that owns the default Security Group.
`name` - The name of the default Security Group.
`description` - The description of the default Security Group. | +| [dhcp\_options](#output\_dhcp\_options) | The configuration for the DHCP Option Set of the VPC.
`id` - The ID of the DHCP Options Set.
`arn` - The ARN of the DHCP Options Set.
`owner` - The ID of the AWS account that owns the DHCP Option Set.

`domain_name` - The suffix domain name to use by default when resolving non Fully Qualified Domain Names.
`domain_name_servers` - A list of name servers to configure in `/etc/resolv.conf`.
`netbios_name_servers` - A list of NetBIOS name servers.
`netbios_node_type` - The NetBIOS node type (1, 2, 4, or 8).
`ntp_servers` - A list of NTP servers to configure. | | [dns\_dnssec\_validation\_enabled](#output\_dns\_dnssec\_validation\_enabled) | Whether or not the VPC has Route53 DNSSEC validation support. | | [dns\_dnssec\_validation\_id](#output\_dns\_dnssec\_validation\_id) | The ID of a configuration for DNSSEC validation. | -| [dns\_hostnames\_enabled](#output\_dns\_hostnames\_enabled) | Whether or not the VPC has DNS hostname support. | -| [dns\_support\_enabled](#output\_dns\_support\_enabled) | Whether or not the VPC has DNS support. | -| [egress\_only\_internet\_gateway\_enabled](#output\_egress\_only\_internet\_gateway\_enabled) | Whether Egress Only Internet Gateway is enabled in the VPC. | -| [egress\_only\_internet\_gateway\_id](#output\_egress\_only\_internet\_gateway\_id) | The ID of the Egress Only Internet Gateway. | +| [dns\_hostnames\_enabled](#output\_dns\_hostnames\_enabled) | Whether instances launched in the VPC receive public DNS hostnames that correspond to their public IP addresses. | +| [dns\_resolution\_enabled](#output\_dns\_resolution\_enabled) | Whether DNS resolution through the Amazon DNS server is supported for the VPC. | +| [egress\_only\_internet\_gateway](#output\_egress\_only\_internet\_gateway) | The configuration for the Egress-only Internet Gateway of the VPC.
`id` - The ID of the Egress-only Internet Gateway. | | [id](#output\_id) | The ID of the VPC. | -| [instance\_tenancy](#output\_instance\_tenancy) | Tenancy of instances spin up within VPC. | -| [internet\_gateway\_arn](#output\_internet\_gateway\_arn) | The ARN of the Internet Gateway. | -| [internet\_gateway\_enabled](#output\_internet\_gateway\_enabled) | Whether Internet Gateway is enabled in the VPC. | -| [internet\_gateway\_id](#output\_internet\_gateway\_id) | The ID of the Internet Gateway. | -| [ipv6\_association\_id](#output\_ipv6\_association\_id) | The association ID for the IPv6 CIDR block. | -| [ipv6\_cidr\_block](#output\_ipv6\_cidr\_block) | The IPv6 CIDR block. | -| [main\_route\_table\_id](#output\_main\_route\_table\_id) | The ID of the main route table associated with this VPC. Note that you can change a VPC's main route table. | -| [name](#output\_name) | The VPC name. | +| [internet\_gateway](#output\_internet\_gateway) | The configuration for the Internet Gateway of the VPC.
`id` - The ID of the Internet Gateway.
`arn` - The ARN of the Internet Gateway.
`owner` - The ID of the AWS account that owns the internet gateway. | +| [ipv4\_cidr\_configurations](#output\_ipv4\_cidr\_configurations) | The list of IPv4 CIDR configurations for the VPC. | +| [ipv4\_cidrs](#output\_ipv4\_cidrs) | The list of IPv4 CIDR blocks for the VPC. | +| [ipv6\_cidr\_configurations](#output\_ipv6\_cidr\_configurations) | The list of IPv6 CIDR configurations for the VPC. | +| [ipv6\_cidrs](#output\_ipv6\_cidrs) | The list of IPv6 CIDR blocks for the VPC. | +| [main\_route\_table](#output\_main\_route\_table) | The configuration for the main Route Table of the VPC. Note that you can change a VPC's main route table.
`id` - The ID of the main Route Table. | +| [name](#output\_name) | The name of the VPC. | +| [network\_address\_usage\_metrics\_enabled](#output\_network\_address\_usage\_metrics\_enabled) | Whether NAU (Network Address Usage) metrics are enabled for the VPC. | +| [owner](#output\_owner) | The ID of the AWS account that owns the VPC. | | [private\_hosted\_zones](#output\_private\_hosted\_zones) | List of associated private Hosted Zone IDs. | -| [secondary\_cidr\_blocks](#output\_secondary\_cidr\_blocks) | List of secondary CIDR blocks of the VPC. | -| [vpn\_gateway\_arn](#output\_vpn\_gateway\_arn) | The ARN of the Virtual Private Gateway. | -| [vpn\_gateway\_asn](#output\_vpn\_gateway\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | -| [vpn\_gateway\_enabled](#output\_vpn\_gateway\_enabled) | Whether VPN Gateway is enabled in the VPC. | -| [vpn\_gateway\_id](#output\_vpn\_gateway\_id) | The ID of the Virtual Private Gateway. | +| [tenancy](#output\_tenancy) | A tenancy option for instances launched into the VPC. | +| [vpn\_gateway](#output\_vpn\_gateway) | The configuration for the virtual private gateway of the VPC.
`id` - The ID of the Virtual Private Gateway.
`arn` - The ARN of the Virtual Private Gateway.
`asn` - The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | diff --git a/modules/vpc/defaults.tf b/modules/vpc/defaults.tf new file mode 100644 index 0000000..5dea42d --- /dev/null +++ b/modules/vpc/defaults.tf @@ -0,0 +1,237 @@ +################################################### +# Default NACL +################################################### + +# INFO: Not supported attributes +# - `subnet_ids` +resource "aws_default_network_acl" "this" { + default_network_acl_id = aws_vpc.this.default_network_acl_id + + dynamic "ingress" { + for_each = (var.default_network_acl.ingress_rules == null + ? ["go"] + : [] + ) + + content { + rule_no = 100 + action = "allow" + protocol = -1 + from_port = 0 + to_port = 0 + cidr_block = "0.0.0.0/0" + } + } + + dynamic "ingress" { + for_each = (var.default_network_acl.ingress_rules == null && local.ipv6_enabled + ? ["go"] + : [] + ) + + content { + rule_no = 101 + action = "allow" + protocol = -1 + from_port = 0 + to_port = 0 + ipv6_cidr_block = "::/0" + } + } + + dynamic "ingress" { + for_each = (var.default_network_acl.ingress_rules != null + ? var.default_network_acl.ingress_rules + : [] + ) + + content { + rule_no = ingress.value.priority + action = lower(ingress.value.action) + protocol = ingress.value.protocol + from_port = ingress.value.from_port + to_port = ingress.value.to_port + cidr_block = ingress.value.ipv4_cidr + ipv6_cidr_block = ingress.value.ipv6_cidr + icmp_type = ingress.value.icmp_type + icmp_code = ingress.value.icmp_code + } + } + + dynamic "egress" { + for_each = (var.default_network_acl.egress_rules == null + ? ["go"] + : [] + ) + + content { + rule_no = 100 + action = "allow" + protocol = -1 + from_port = 0 + to_port = 0 + cidr_block = "0.0.0.0/0" + } + } + + dynamic "egress" { + for_each = (var.default_network_acl.egress_rules == null && local.ipv6_enabled + ? ["go"] + : [] + ) + + content { + rule_no = 101 + action = "allow" + protocol = -1 + from_port = 0 + to_port = 0 + ipv6_cidr_block = "::/0" + } + } + + dynamic "egress" { + for_each = (var.default_network_acl.egress_rules != null + ? var.default_network_acl.egress_rules + : [] + ) + + content { + rule_no = egress.value.priority + action = lower(egress.value.action) + protocol = egress.value.protocol + from_port = egress.value.from_port + to_port = egress.value.to_port + cidr_block = egress.value.ipv4_cidr + ipv6_cidr_block = egress.value.ipv6_cidr + icmp_type = egress.value.icmp_type + icmp_code = egress.value.icmp_code + } + } + + tags = merge( + { + "Name" = coalesce(var.default_network_acl.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) + + lifecycle { + ignore_changes = [subnet_ids] + } +} + + +################################################### +# Default Route Table +################################################### + +# resource "aws_default_route_table" "this" { +# default_route_table_id = aws_vpc.this.default_route_table_id +# +# tags = merge( +# { +# "Name" = coalesce(var.default_route_table.name, local.metadata.name) +# }, +# local.module_tags, +# var.tags, +# ) +# } + + +################################################### +# Default Security Group +################################################### + +resource "aws_default_security_group" "this" { + vpc_id = aws_vpc.this.id + + dynamic "ingress" { + for_each = (var.default_security_group.ingress_rules == null + ? ["go"] + : [] + ) + + content { + protocol = -1 + from_port = 0 + to_port = 0 + self = true + } + } + + dynamic "ingress" { + for_each = (var.default_security_group.ingress_rules != null + ? var.default_security_group.ingress_rules + : [] + ) + + content { + description = ingress.value.description + protocol = ingress.value.protocol + from_port = ingress.value.from_port + to_port = ingress.value.to_port + cidr_blocks = ingress.value.ipv4_cidrs + ipv6_cidr_blocks = ingress.value.ipv6_cidrs + prefix_list_ids = ingress.value.prefix_lists + security_groups = ingress.value.security_groups + self = ingress.value.self + } + } + + dynamic "egress" { + for_each = (var.default_security_group.egress_rules == null + ? ["go"] + : [] + ) + + content { + protocol = -1 + from_port = 0 + to_port = 0 + cidr_blocks = ["0.0.0.0/0"] + } + } + + dynamic "egress" { + for_each = (var.default_security_group.egress_rules == null && local.ipv6_enabled + ? ["go"] + : [] + ) + + content { + protocol = -1 + from_port = 0 + to_port = 0 + ipv6_cidr_blocks = ["::/0"] + } + } + + dynamic "egress" { + for_each = (var.default_security_group.egress_rules != null + ? var.default_security_group.egress_rules + : [] + ) + + content { + description = egress.value.description + protocol = egress.value.protocol + from_port = egress.value.from_port + to_port = egress.value.to_port + cidr_blocks = egress.value.ipv4_cidrs + ipv6_cidr_blocks = egress.value.ipv6_cidrs + prefix_list_ids = egress.value.prefix_lists + security_groups = egress.value.security_groups + self = egress.value.self + } + } + + tags = merge( + { + "Name" = coalesce(var.default_security_group.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) +} diff --git a/modules/vpc/dhcp-options.tf b/modules/vpc/dhcp-options.tf new file mode 100644 index 0000000..74b5317 --- /dev/null +++ b/modules/vpc/dhcp-options.tf @@ -0,0 +1,48 @@ +data "aws_region" "this" {} + +locals { + region = data.aws_region.this.name + + default_dhcp_options_domain_name = (local.region != "us-east-1" + ? "${local.region}.compute.internal" + : "ec2.internal" + ) +} + + +################################################### +# DHCP Options +################################################### + +resource "aws_vpc_dhcp_options" "this" { + count = var.dhcp_options.enabled ? 1 : 0 + + domain_name = (length(compact([var.dhcp_options.domain_name])) > 0 + ? var.dhcp_options.domain_name + : local.default_dhcp_options_domain_name + ) + domain_name_servers = var.dhcp_options.domain_name_servers + ipv6_address_preferred_lease_time = var.dhcp_options.ipv6_address_preferred_lease_time + 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 + + tags = merge( + { + "Name" = coalesce(var.dhcp_options.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_vpc_dhcp_options_association" "this" { + count = var.dhcp_options.enabled ? 1 : 0 + + vpc_id = aws_vpc.this.id + dhcp_options_id = aws_vpc_dhcp_options.this[0].id +} diff --git a/modules/vpc/gateways.tf b/modules/vpc/gateways.tf new file mode 100644 index 0000000..edde2da --- /dev/null +++ b/modules/vpc/gateways.tf @@ -0,0 +1,79 @@ +################################################### +# Internet Gateway +################################################### + +# INFO: Not supported attributes +# - `vpc_id` +resource "aws_internet_gateway" "this" { + count = var.internet_gateway.enabled ? 1 : 0 + + tags = merge( + { + "Name" = coalesce(var.internet_gateway.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) +} + +resource "aws_internet_gateway_attachment" "this" { + count = var.internet_gateway.enabled ? 1 : 0 + + vpc_id = aws_vpc.this.id + internet_gateway_id = aws_internet_gateway.this[0].id +} + + +################################################### +# Egress Only Internet Gateway (IPv6) +################################################### + +resource "aws_egress_only_internet_gateway" "this" { + count = var.egress_only_internet_gateway.enabled ? 1 : 0 + + vpc_id = aws_vpc.this.id + + tags = merge( + { + "Name" = coalesce(var.egress_only_internet_gateway.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) + + lifecycle { + precondition { + condition = local.ipv6_enabled + error_message = "Egress Only Internet Gateway (IPv6) cannot be enabled if IPv6 is not enabled." + } + } +} + + +################################################### +# Virtual Private Gateway +################################################### + +# INFO: Not supported attributes +# - `vpc_id` +# - `availability_zone` +resource "aws_vpn_gateway" "this" { + count = var.vpn_gateway.enabled ? 1 : 0 + + amazon_side_asn = var.vpn_gateway.asn + + tags = merge( + { + "Name" = coalesce(var.vpn_gateway.name, local.metadata.name) + }, + local.module_tags, + var.tags, + ) +} + +resource "aws_vpn_gateway_attachment" "this" { + count = var.vpn_gateway.enabled ? 1 : 0 + + vpc_id = aws_vpc.this.id + vpn_gateway_id = aws_vpn_gateway.this[0].id +} diff --git a/modules/vpc/main.tf b/modules/vpc/main.tf index 2ab5a8a..42bf003 100644 --- a/modules/vpc/main.tf +++ b/modules/vpc/main.tf @@ -14,100 +14,82 @@ locals { } : {} } -resource "aws_vpc" "this" { - cidr_block = var.cidr_block - assign_generated_ipv6_cidr_block = var.ipv6_enabled - - instance_tenancy = var.instance_tenancy - - enable_dns_hostnames = var.dns_hostnames_enabled - enable_dns_support = var.dns_support_enabled - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, - ) -} - -resource "aws_vpc_ipv4_cidr_block_association" "this" { - for_each = toset(var.secondary_cidr_blocks) - - vpc_id = aws_vpc.this.id - cidr_block = each.key -} - - -################################################### -# Associated Route53 Private Hosted Zones -################################################### - -resource "aws_route53_zone_association" "this" { - for_each = toset(var.private_hosted_zones) - - vpc_id = aws_vpc.this.id - zone_id = each.value -} - - -################################################### -# Route53 DNSSEC Validation -################################################### - -resource "aws_route53_resolver_dnssec_config" "this" { - count = var.dns_dnssec_validation_enabled ? 1 : 0 - - resource_id = aws_vpc.this.id +locals { + ipv4_secondary_cidrs = slice(var.ipv4_cidrs, 1, length(var.ipv4_cidrs)) + ipv6_enabled = length(var.ipv6_cidrs) > 0 + tenancy = { + "DEFAULT" = "default" + "DEDICATED" = "dedicated" + } } ################################################### -# DHCP Options +# VPC ################################################### -data "aws_region" "current" {} - -locals { - current_region = data.aws_region.current.name - default_dhcp_options_domain_name = local.current_region != "us-east-1" ? "${local.current_region}.compute.internal" : "ec2.internal" -} - -resource "aws_vpc_dhcp_options" "this" { - count = var.dhcp_options_enabled ? 1 : 0 - - domain_name = var.dhcp_options_domain_name != "" ? var.dhcp_options_domain_name : local.default_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 - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, +resource "aws_vpc" "this" { + ## IPv4 CIDR Blocks + cidr_block = (var.ipv4_cidrs[0].type == "MANUAL" + ? var.ipv4_cidrs[0].cidr + : null + ) + ipv4_ipam_pool_id = (var.ipv4_cidrs[0].type == "IPAM_POOL" + ? var.ipv4_cidrs[0].ipam_pool.id + : null + ) + ipv4_netmask_length = (var.ipv4_cidrs[0].type == "IPAM_POOL" + ? var.ipv4_cidrs[0].ipam_pool.netmask_length + : null ) -} -resource "aws_vpc_dhcp_options_association" "this" { - count = var.dhcp_options_enabled ? 1 : 0 - vpc_id = aws_vpc.this.id - dhcp_options_id = aws_vpc_dhcp_options.this[0].id -} + ## IPv6 CIDR Blocks + # TODO: Want to manage IPv6 CIDRs with `aws_vpc_ipv6_cidr_block_association` resource. But, there are unsupported featrues yet. + assign_generated_ipv6_cidr_block = (local.ipv6_enabled + ? (var.ipv6_cidrs[0].type == "AMAZON" + ? true + : null + ) + : null + ) + ipv6_cidr_block_network_border_group = (local.ipv6_enabled + ? (var.ipv6_cidrs[0].type == "AMAZON" + ? var.ipv6_cidrs[0].amazon.network_border_group + : null + ) + : null + ) + ipv6_ipam_pool_id = (local.ipv6_enabled + ? (var.ipv6_cidrs[0].type == "IPAM_POOL" + ? var.ipv6_cidrs[0].ipam_pool.id + : null + ) + : null + ) + ipv6_cidr_block = (local.ipv6_enabled + ? (var.ipv6_cidrs[0].type == "IPAM_POOL" + ? var.ipv6_cidrs[0].ipam_pool.cidr + : null + ) + : null + ) + ipv6_netmask_length = (local.ipv6_enabled + ? (var.ipv6_cidrs[0].type == "IPAM_POOL" + ? var.ipv6_cidrs[0].ipam_pool.netmask_length + : null + ) + : null + ) -################################################### -# Internet Gateway -################################################### + ## Attributes + instance_tenancy = local.tenancy[var.tenancy] -resource "aws_internet_gateway" "this" { - count = var.internet_gateway_enabled ? 1 : 0 + enable_network_address_usage_metrics = var.network_address_usage_metrics_enabled - vpc_id = aws_vpc.this.id + enable_dns_hostnames = var.dns_hostnames_enabled + enable_dns_support = var.dns_resolution_enabled tags = merge( { @@ -120,41 +102,41 @@ resource "aws_internet_gateway" "this" { ################################################### -# Egress Only Internet Gateway (IPv6) +# Additional CIDR Blocks for the VPC ################################################### -resource "aws_egress_only_internet_gateway" "this" { - count = var.ipv6_enabled && var.egress_only_internet_gateway_enabled ? 1 : 0 +resource "aws_vpc_ipv4_cidr_block_association" "this" { + count = length(var.ipv4_cidrs) > 0 ? length(var.ipv4_cidrs) - 1 : 0 vpc_id = aws_vpc.this.id - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, + cidr_block = (var.ipv4_cidrs[count.index + 1].type == "MANUAL" + ? var.ipv4_cidrs[count.index + 1].cidr + : null + ) + ipv4_ipam_pool_id = (var.ipv4_cidrs[count.index + 1].type == "IPAM_POOL" + ? var.ipv4_cidrs[count.index + 1].ipam_pool.id + : null + ) + ipv4_netmask_length = (var.ipv4_cidrs[count.index + 1].type == "IPAM_POOL" + ? var.ipv4_cidrs[count.index + 1].ipam_pool.netmask_length + : null ) } - -################################################### -# Virtual Private Gateway -################################################### - -resource "aws_vpn_gateway" "this" { - count = var.vpn_gateway_enabled ? 1 : 0 +resource "aws_vpc_ipv6_cidr_block_association" "this" { + count = length(var.ipv6_cidrs) > 0 ? length(var.ipv6_cidrs) - 1 : 0 vpc_id = aws_vpc.this.id - # TODO: I don't know why this variable is needed - # availability_zone = "ap-northeast-2a" - amazon_side_asn = var.vpn_gateway_asn - - tags = merge( - { - "Name" = local.metadata.name - }, - local.module_tags, - var.tags, + ipv6_cidr_block = (var.ipv6_cidrs[count.index + 1].type == "IPAM_POOL" + ? var.ipv6_cidrs[count.index + 1].ipam_pool.cidr + : null + ) + ipv6_ipam_pool_id = (var.ipv6_cidrs[count.index + 1].type == "IPAM_POOL" + ? var.ipv6_cidrs[count.index + 1].ipam_pool.id + : null + ) + ipv6_netmask_length = (var.ipv6_cidrs[count.index + 1].type == "IPAM_POOL" + ? var.ipv6_cidrs[count.index + 1].ipam_pool.netmask_length + : null ) } diff --git a/modules/vpc/migrations.tf b/modules/vpc/migrations.tf new file mode 100644 index 0000000..83a0f7e --- /dev/null +++ b/modules/vpc/migrations.tf @@ -0,0 +1,5 @@ +# 2023-02-01 +moved { + from = aws_resourcegroups_group.this[0] + to = module.resource_group[0].aws_resourcegroups_group.this +} diff --git a/modules/vpc/outputs.tf b/modules/vpc/outputs.tf index e9c1cdf..bdc066b 100644 --- a/modules/vpc/outputs.tf +++ b/modules/vpc/outputs.tf @@ -1,53 +1,144 @@ output "name" { - description = "The VPC name." + description = "The name of the VPC." value = var.name } +output "owner" { + description = "The ID of the AWS account that owns the VPC." + value = aws_vpc.this.owner_id +} + output "id" { description = "The ID of the VPC." value = aws_vpc.this.id } output "arn" { - description = "The ARN of the VPC." + description = "The ARN (Amazon Resource Name) of the VPC." value = aws_vpc.this.arn } -output "cidr_block" { - description = "The CIDR block of the VPC." - value = aws_vpc.this.cidr_block +output "ipv4_cidrs" { + description = "The list of IPv4 CIDR blocks for the VPC." + value = concat( + [aws_vpc.this.cidr_block], + [ + for association in aws_vpc_ipv4_cidr_block_association.this : + association.cidr_block + ] + ) } -output "secondary_cidr_blocks" { - description = "List of secondary CIDR blocks of the VPC." - value = var.secondary_cidr_blocks +output "ipv4_cidr_configurations" { + description = "The list of IPv4 CIDR configurations for the VPC." + value = merge({ + (aws_vpc.this.cidr_block) = { + type = aws_vpc.this.ipv4_ipam_pool_id != null ? "IPAM_POOL" : "MANUAL" + + ipam_pool = (aws_vpc.this.ipv4_ipam_pool_id != null + ? { + id = aws_vpc.this.ipv4_ipam_pool_id + netmask_length = aws_vpc.this.ipv4_netmask_length + } + : null + ) + }, + }, { + for association in aws_vpc_ipv4_cidr_block_association.this : + (association.cidr_block) => { + type = association.ipv4_ipam_pool_id != null ? "IPAM_POOL" : "MANUAL" + ipam_pool = (association.ipv4_ipam_pool_id != null + ? { + id = association.ipv4_ipam_pool_id + netmask_length = association.ipv4_netmask_length + } + : null + ) + } + }) } -output "ipv6_cidr_block" { - description = "The IPv6 CIDR block." - value = aws_vpc.this.ipv6_cidr_block +output "ipv6_cidrs" { + description = "The list of IPv6 CIDR blocks for the VPC." + value = (local.ipv6_enabled + ? concat( + [aws_vpc.this.ipv6_cidr_block], + [ + for association in aws_vpc_ipv6_cidr_block_association.this : + association.ipv6_cidr_block + ] + ) + : [] + ) } -output "ipv6_association_id" { - description = "The association ID for the IPv6 CIDR block." - value = aws_vpc.this.ipv6_association_id +output "ipv6_cidr_configurations" { + description = "The list of IPv6 CIDR configurations for the VPC." + value = (local.ipv6_enabled + ? merge({ + (aws_vpc.this.ipv6_cidr_block) = { + type = length(compact([aws_vpc.this.ipv6_ipam_pool_id])) > 0 ? "IPAM_POOL" : "AMAZON" + amazon = (length(compact([aws_vpc.this.ipv6_ipam_pool_id])) < 1 + ? { + network_border_group = aws_vpc.this.ipv6_cidr_block_network_border_group + } + : null + ) + ipam_pool = (length(compact([aws_vpc.this.ipv6_ipam_pool_id])) > 0 + ? { + id = aws_vpc.this.ipv6_ipam_pool_id + netmask_length = aws_vpc.this.ipv6_netmask_length + } + : null + ) + }, + }, { + for association in aws_vpc_ipv6_cidr_block_association.this : + (association.ipv6_cidr_block) => { + type = length(compact([association.ipv6_ipam_pool_id])) > 0 ? "IPAM_POOL" : "AMAZON" + amazon = (length(compact([association.ipv6_ipam_pool_id])) < 1 + ? { + # TODO: Not supported yet + network_border_group = null + } + : null + ) + ipam_pool = (length(compact([association.ipv6_ipam_pool_id])) > 0 + ? { + id = association.ipv6_ipam_pool_id + netmask_length = association.ipv6_netmask_length + } + : null + ) + } + }) + : {} + ) } -output "instance_tenancy" { - description = "Tenancy of instances spin up within VPC." - value = aws_vpc.this.instance_tenancy +output "tenancy" { + description = "A tenancy option for instances launched into the VPC." + value = { + for k, v in local.tenancy : + v => k + }[aws_vpc.this.instance_tenancy] } -output "dns_support_enabled" { - description = "Whether or not the VPC has DNS support." - value = aws_vpc.this.enable_dns_support +output "network_address_usage_metrics_enabled" { + description = "Whether NAU (Network Address Usage) metrics are enabled for the VPC." + value = aws_vpc.this.enable_network_address_usage_metrics } output "dns_hostnames_enabled" { - description = "Whether or not the VPC has DNS hostname support." + description = "Whether instances launched in the VPC receive public DNS hostnames that correspond to their public IP addresses." value = aws_vpc.this.enable_dns_hostnames } +output "dns_resolution_enabled" { + description = "Whether DNS resolution through the Amazon DNS server is supported for the VPC." + value = aws_vpc.this.enable_dns_support +} + output "dns_dnssec_validation_enabled" { description = "Whether or not the VPC has Route53 DNSSEC validation support." value = var.dns_dnssec_validation_enabled @@ -55,7 +146,7 @@ output "dns_dnssec_validation_enabled" { output "dns_dnssec_validation_id" { description = "The ID of a configuration for DNSSEC validation." - value = try(aws_route53_resolver_dnssec_config.this.*.id[0], null) + value = one(aws_route53_resolver_dnssec_config.this[*].id) } output "private_hosted_zones" { @@ -63,82 +154,132 @@ output "private_hosted_zones" { value = values(aws_route53_zone_association.this)[*].zone_id } -output "default_security_group_id" { - description = "The ID of the security group created by default on VPC creation." - value = aws_vpc.this.default_security_group_id +output "default_network_acl" { + description = < 0 + error_message = "At least one IPv4 CIDR must be defined." + } + validation { + condition = alltrue([ + for ipv4_cidr in var.ipv4_cidrs : + contains(["MANUAL", "IPAM_POOL"], ipv4_cidr.type) + ]) + error_message = "Valid values for `type` of each IPv4 CIDR are `MANUAL` and `IPAM_POOL`." + } } -variable "ipv6_enabled" { - description = "Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or the size of the CIDR block." - type = bool - default = false +variable "ipv6_cidrs" { + description = <= 64512 && var.vpn_gateway.asn <= 65534, + var.vpn_gateway.asn >= 4200000000 && var.vpn_gateway.asn <= 4294967294, + ]) + error_message = "Value of `asn` must be in the `64512` - `65534` or `4200000000` - `4294967294` range." + } } variable "tags" { - description = "A map of tags to add to all resources." + description = "(Optional) A map of tags to add to all resources." type = map(string) default = {} + nullable = false } variable "module_tags_enabled" { - description = "Whether to create AWS Resource Tags for the module informations." + description = "(Optional) Whether to create AWS Resource Tags for the module informations." type = bool default = true + nullable = false } @@ -128,19 +349,22 @@ variable "module_tags_enabled" { ################################################### variable "resource_group_enabled" { - description = "Whether to create Resource Group to find and group AWS resources which are created by this module." + description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." type = bool default = true + nullable = false } variable "resource_group_name" { - description = "The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." + description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." type = string default = "" + nullable = false } variable "resource_group_description" { - description = "The description of Resource Group." + description = "(Optional) The description of Resource Group." type = string default = "Managed by Terraform." + nullable = false } diff --git a/modules/vpc/versions.tf b/modules/vpc/versions.tf index 6078ceb..0cf17ea 100644 --- a/modules/vpc/versions.tf +++ b/modules/vpc/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = ">= 1.6" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.45" + version = ">= 5.46" } } }