From ae60f5be04efd0b8c39dc48f9a1560adb05e6455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Ruiz?= <50803935+agustin58ruiz@users.noreply.github.com> Date: Fri, 16 May 2025 21:00:29 -0300 Subject: [PATCH 1/4] Adding private zone for route53 --- main.tf | 2 +- variables.tf | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/main.tf b/main.tf index add0941..bace49e 100644 --- a/main.tf +++ b/main.tf @@ -135,7 +135,7 @@ locals { data "aws_route53_zone" "this" { count = local.create_domain_name && var.create_domain_records ? 1 : 0 - + private_zone = var.private_zone name = coalesce(var.hosted_zone_name, local.stripped_domain_name) } diff --git a/variables.tf b/variables.tf index 3e2219d..3663017 100644 --- a/variables.tf +++ b/variables.tf @@ -156,6 +156,12 @@ variable "hosted_zone_name" { default = null } +variable "private_zone" { + description = "Whether the hosted zone is private or not" + type = bool + default = false +} + variable "domain_name_certificate_arn" { description = "The ARN of an AWS-managed certificate that will be used by the endpoint for the domain name. AWS Certificate Manager is the only supported source" type = string From 1913ddb0c52b8b998e35267a9d1e1b439e3f94c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Ruiz?= <50803935+agustin58ruiz@users.noreply.github.com> Date: Fri, 16 May 2025 21:11:30 -0300 Subject: [PATCH 2/4] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2f37273..1a5fdd3 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,7 @@ module "api_gateway" { | [ip\_address\_type](#input\_ip\_address\_type) | The IP address types that can invoke the API. Valid values: ipv4, dualstack. Use ipv4 to allow only IPv4 addresses to invoke your API, or use dualstack to allow both IPv4 and IPv6 addresses to invoke your API. Defaults to ipv4. | `string` | `null` | no | | [mutual\_tls\_authentication](#input\_mutual\_tls\_authentication) | The mutual TLS authentication configuration for the domain name | `map(string)` | `{}` | no | | [name](#input\_name) | The name of the API. Must be less than or equal to 128 characters in length | `string` | `""` | no | +| [private\_zone](#input\_private\_zone) | Whether the hosted zone is private or not. `false` for public hosted zone. `true` for private hosted zone. | `bool` | `false` | no | | [protocol\_type](#input\_protocol\_type) | The API protocol. Valid values: `HTTP`, `WEBSOCKET` | `string` | `"HTTP"` | no | | [route\_key](#input\_route\_key) | Part of quick create. Specifies any route key. Applicable for HTTP APIs | `string` | `null` | no | | [route\_selection\_expression](#input\_route\_selection\_expression) | The route selection expression for the API. Defaults to `$request.method $request.path` | `string` | `null` | no | From 44749bdfa601f0895c9c5d8308fa3807acc7e926 Mon Sep 17 00:00:00 2001 From: agustin58ruiz Date: Sat, 17 May 2025 21:30:31 -0300 Subject: [PATCH 3/4] pre-commit run -a successfully --- .editorconfig | 66 +- .github/workflows/lock.yml | 42 +- .github/workflows/pr-title.yml | 104 +-- .github/workflows/pre-commit.yml | 198 ++--- .github/workflows/release.yml | 74 +- .github/workflows/stale-actions.yaml | 64 +- .gitignore | 70 +- .pre-commit-config.yaml | 62 +- .releaserc.json | 90 +- CHANGELOG.md | 694 ++++++++-------- LICENSE | 352 ++++---- README.md | 370 ++++----- UPGRADE-5.0.md | 430 +++++----- examples/README.md | 16 +- examples/complete-http/README.md | 38 +- examples/complete-http/api.yaml | 44 +- examples/complete-http/main.tf | 702 ++++++++-------- examples/complete-http/outputs.tf | 300 +++---- examples/complete-http/variables.tf | 10 +- examples/complete-http/versions.tf | 44 +- examples/vpc-link-http/README.md | 38 +- examples/vpc-link-http/main.tf | 452 +++++----- examples/vpc-link-http/outputs.tf | 290 +++---- examples/vpc-link-http/versions.tf | 28 +- examples/websocket/README.md | 100 +-- examples/websocket/function/onConnect.js | 54 +- examples/websocket/function/onDisconnect.js | 66 +- examples/websocket/function/sendMessage.js | 108 +-- examples/websocket/main.tf | 486 +++++------ examples/websocket/outputs.tf | 290 +++---- examples/websocket/versions.tf | 20 +- main.tf | 872 ++++++++++---------- migrations.tf | 26 +- outputs.tf | 290 +++---- variables.tf | 786 +++++++++--------- versions.tf | 20 +- wrappers/README.md | 6 +- wrappers/main.tf | 1 + wrappers/versions.tf | 20 +- 39 files changed, 3862 insertions(+), 3861 deletions(-) diff --git a/.editorconfig b/.editorconfig index 1df806f..d725693 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,33 +1,33 @@ -# EditorConfig is awesome: http://EditorConfig.org -# Uses editorconfig to maintain consistent coding styles - -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -charset = utf-8 -end_of_line = lf -indent_size = 2 -indent_style = space -insert_final_newline = true -max_line_length = 80 -trim_trailing_whitespace = true - -[*.py] -indent_size = 4 - -[*.{tf,tfvars}] -indent_size = 2 -indent_style = space - -[*.md] -max_line_length = 0 -trim_trailing_whitespace = false - -[Makefile] -tab_width = 2 -indent_style = tab - -[COMMIT_EDITMSG] -max_line_length = 0 +# EditorConfig is awesome: http://EditorConfig.org +# Uses editorconfig to maintain consistent coding styles + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 80 +trim_trailing_whitespace = true + +[*.py] +indent_size = 4 + +[*.{tf,tfvars}] +indent_size = 2 +indent_style = space + +[*.md] +max_line_length = 0 +trim_trailing_whitespace = false + +[Makefile] +tab_width = 2 +indent_style = tab + +[COMMIT_EDITMSG] +max_line_length = 0 diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index bd5f2df..d95816a 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -1,21 +1,21 @@ -name: 'Lock Threads' - -on: - schedule: - - cron: '50 1 * * *' - -jobs: - lock: - runs-on: ubuntu-latest - steps: - - uses: dessant/lock-threads@v5 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - issue-comment: > - I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. - If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. - issue-inactive-days: '30' - pr-comment: > - I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. - If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. - pr-inactive-days: '30' +name: 'Lock Threads' + +on: + schedule: + - cron: '50 1 * * *' + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v5 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + issue-comment: > + I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. + If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. + issue-inactive-days: '30' + pr-comment: > + I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. + If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. + pr-inactive-days: '30' diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 1e50760..9b7b644 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -1,52 +1,52 @@ -name: 'Validate PR title' - -on: - pull_request_target: - types: - - opened - - edited - - synchronize - -jobs: - main: - name: Validate PR title - runs-on: ubuntu-latest - steps: - # Please look up the latest version from - # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@v5.5.3 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - # Configure which types are allowed. - # Default: https://github.com/commitizen/conventional-commit-types - types: | - fix - feat - docs - ci - chore - # Configure that a scope must always be provided. - requireScope: false - # Configure additional validation for the subject based on a regex. - # This example ensures the subject starts with an uppercase character. - subjectPattern: ^[A-Z].+$ - # If `subjectPattern` is configured, you can use this property to override - # the default error message that is shown when the pattern doesn't match. - # The variables `subject` and `title` can be used within the message. - subjectPatternError: | - The subject "{subject}" found in the pull request title "{title}" - didn't match the configured pattern. Please ensure that the subject - starts with an uppercase character. - # For work-in-progress PRs you can typically use draft pull requests - # from Github. However, private repositories on the free plan don't have - # this option and therefore this action allows you to opt-in to using the - # special "[WIP]" prefix to indicate this state. This will avoid the - # validation of the PR title and the pull request checks remain pending. - # Note that a second check will be reported if this is enabled. - wip: true - # When using "Squash and merge" on a PR with only one commit, GitHub - # will suggest using that commit message instead of the PR title for the - # merge commit, and it's easy to commit this by mistake. Enable this option - # to also validate the commit message for one commit PRs. - validateSingleCommit: false +name: 'Validate PR title' + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + # Please look up the latest version from + # https://github.com/amannn/action-semantic-pull-request/releases + - uses: amannn/action-semantic-pull-request@v5.5.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # Configure which types are allowed. + # Default: https://github.com/commitizen/conventional-commit-types + types: | + fix + feat + docs + ci + chore + # Configure that a scope must always be provided. + requireScope: false + # Configure additional validation for the subject based on a regex. + # This example ensures the subject starts with an uppercase character. + subjectPattern: ^[A-Z].+$ + # If `subjectPattern` is configured, you can use this property to override + # the default error message that is shown when the pattern doesn't match. + # The variables `subject` and `title` can be used within the message. + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + starts with an uppercase character. + # For work-in-progress PRs you can typically use draft pull requests + # from Github. However, private repositories on the free plan don't have + # this option and therefore this action allows you to opt-in to using the + # special "[WIP]" prefix to indicate this state. This will avoid the + # validation of the PR title and the pull request checks remain pending. + # Note that a second check will be reported if this is enabled. + wip: true + # When using "Squash and merge" on a PR with only one commit, GitHub + # will suggest using that commit message instead of the PR title for the + # merge commit, and it's easy to commit this by mistake. Enable this option + # to also validate the commit message for one commit PRs. + validateSingleCommit: false diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index a19ff83..623d3b6 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,99 +1,99 @@ -name: Pre-Commit - -on: - pull_request: - branches: - - main - - master - -env: - TERRAFORM_DOCS_VERSION: v0.19.0 - TFLINT_VERSION: v0.53.0 - -jobs: - collectInputs: - name: Collect workflow inputs - runs-on: ubuntu-latest - outputs: - directories: ${{ steps.dirs.outputs.directories }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Get root directories - id: dirs - uses: clowdhaus/terraform-composite-actions/directories@v1.9.0 - - preCommitMinVersions: - name: Min TF pre-commit - needs: collectInputs - runs-on: ubuntu-latest - strategy: - matrix: - directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} - steps: - # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 - - name: Delete huge unnecessary tools folder - run: | - rm -rf /opt/hostedtoolcache/CodeQL - rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk - rm -rf /opt/hostedtoolcache/Ruby - rm -rf /opt/hostedtoolcache/go - - - name: Checkout - uses: actions/checkout@v4 - - - name: Terraform min/max versions - id: minMax - uses: clowdhaus/terraform-min-max@v1.3.1 - with: - directory: ${{ matrix.directory }} - - - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} - # Run only validate pre-commit check on min version supported - if: ${{ matrix.directory != '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 - with: - terraform-version: ${{ steps.minMax.outputs.minVersion }} - tflint-version: ${{ env.TFLINT_VERSION }} - args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*' - - - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} - # Run only validate pre-commit check on min version supported - if: ${{ matrix.directory == '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 - with: - terraform-version: ${{ steps.minMax.outputs.minVersion }} - tflint-version: ${{ env.TFLINT_VERSION }} - args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)' - - preCommitMaxVersion: - name: Max TF pre-commit - runs-on: ubuntu-latest - needs: collectInputs - steps: - # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 - - name: Delete huge unnecessary tools folder - run: | - rm -rf /opt/hostedtoolcache/CodeQL - rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk - rm -rf /opt/hostedtoolcache/Ruby - rm -rf /opt/hostedtoolcache/go - - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{github.event.pull_request.head.repo.full_name}} - - - name: Terraform min/max versions - id: minMax - uses: clowdhaus/terraform-min-max@v1.3.1 - - - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 - with: - terraform-version: ${{ steps.minMax.outputs.maxVersion }} - tflint-version: ${{ env.TFLINT_VERSION }} - terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }} - install-hcledit: true +name: Pre-Commit + +on: + pull_request: + branches: + - main + - master + +env: + TERRAFORM_DOCS_VERSION: v0.19.0 + TFLINT_VERSION: v0.53.0 + +jobs: + collectInputs: + name: Collect workflow inputs + runs-on: ubuntu-latest + outputs: + directories: ${{ steps.dirs.outputs.directories }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get root directories + id: dirs + uses: clowdhaus/terraform-composite-actions/directories@v1.9.0 + + preCommitMinVersions: + name: Min TF pre-commit + needs: collectInputs + runs-on: ubuntu-latest + strategy: + matrix: + directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} + steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + + - name: Checkout + uses: actions/checkout@v4 + + - name: Terraform min/max versions + id: minMax + uses: clowdhaus/terraform-min-max@v1.3.1 + with: + directory: ${{ matrix.directory }} + + - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} + # Run only validate pre-commit check on min version supported + if: ${{ matrix.directory != '.' }} + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 + with: + terraform-version: ${{ steps.minMax.outputs.minVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} + args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*' + + - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} + # Run only validate pre-commit check on min version supported + if: ${{ matrix.directory == '.' }} + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 + with: + terraform-version: ${{ steps.minMax.outputs.minVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} + args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)' + + preCommitMaxVersion: + name: Max TF pre-commit + runs-on: ubuntu-latest + needs: collectInputs + steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + repository: ${{github.event.pull_request.head.repo.full_name}} + + - name: Terraform min/max versions + id: minMax + uses: clowdhaus/terraform-min-max@v1.3.1 + + - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 + with: + terraform-version: ${{ steps.minMax.outputs.maxVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} + terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }} + install-hcledit: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a94226..a8a88f3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,37 +1,37 @@ -name: Release - -on: - workflow_dispatch: - push: - branches: - - main - - master - paths: - - '**/*.tpl' - - '**/*.py' - - '**/*.tf' - - '.github/workflows/release.yml' - -jobs: - release: - name: Release - runs-on: ubuntu-latest - # Skip running release workflow on forks - if: github.repository_owner == 'terraform-aws-modules' - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Release - uses: cycjimmy/semantic-release-action@v4 - with: - semantic_version: 23.0.2 - extra_plugins: | - @semantic-release/changelog@6.0.3 - @semantic-release/git@10.0.1 - conventional-changelog-conventionalcommits@7.0.2 - env: - GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} +name: Release + +on: + workflow_dispatch: + push: + branches: + - main + - master + paths: + - '**/*.tpl' + - '**/*.py' + - '**/*.tf' + - '.github/workflows/release.yml' + +jobs: + release: + name: Release + runs-on: ubuntu-latest + # Skip running release workflow on forks + if: github.repository_owner == 'terraform-aws-modules' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Release + uses: cycjimmy/semantic-release-action@v4 + with: + semantic_version: 23.0.2 + extra_plugins: | + @semantic-release/changelog@6.0.3 + @semantic-release/git@10.0.1 + conventional-changelog-conventionalcommits@7.0.2 + env: + GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} diff --git a/.github/workflows/stale-actions.yaml b/.github/workflows/stale-actions.yaml index 6ccd0ed..22fcf32 100644 --- a/.github/workflows/stale-actions.yaml +++ b/.github/workflows/stale-actions.yaml @@ -1,32 +1,32 @@ -name: 'Mark or close stale issues and PRs' -on: - schedule: - - cron: '0 0 * * *' - -jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v9 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - # Staling issues and PR's - days-before-stale: 30 - stale-issue-label: stale - stale-pr-label: stale - stale-issue-message: | - This issue has been automatically marked as stale because it has been open 30 days - with no activity. Remove stale label or comment or this issue will be closed in 10 days - stale-pr-message: | - This PR has been automatically marked as stale because it has been open 30 days - with no activity. Remove stale label or comment or this PR will be closed in 10 days - # Not stale if have this labels or part of milestone - exempt-issue-labels: bug,wip,on-hold - exempt-pr-labels: bug,wip,on-hold - exempt-all-milestones: true - # Close issue operations - # Label will be automatically removed if the issues are no longer closed nor locked. - days-before-close: 10 - delete-branch: true - close-issue-message: This issue was automatically closed because of stale in 10 days - close-pr-message: This PR was automatically closed because of stale in 10 days +name: 'Mark or close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + # Staling issues and PR's + days-before-stale: 30 + stale-issue-label: stale + stale-pr-label: stale + stale-issue-message: | + This issue has been automatically marked as stale because it has been open 30 days + with no activity. Remove stale label or comment or this issue will be closed in 10 days + stale-pr-message: | + This PR has been automatically marked as stale because it has been open 30 days + with no activity. Remove stale label or comment or this PR will be closed in 10 days + # Not stale if have this labels or part of milestone + exempt-issue-labels: bug,wip,on-hold + exempt-pr-labels: bug,wip,on-hold + exempt-all-milestones: true + # Close issue operations + # Label will be automatically removed if the issues are no longer closed nor locked. + days-before-close: 10 + delete-branch: true + close-issue-message: This issue was automatically closed because of stale in 10 days + close-pr-message: This PR was automatically closed because of stale in 10 days diff --git a/.gitignore b/.gitignore index 3d65725..f945184 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,35 @@ -# Local .terraform directories -**/.terraform/* - -# Terraform lockfile -.terraform.lock.hcl - -# .tfstate files -*.tfstate -*.tfstate.* - -# Crash log files -crash.log - -# Exclude all .tfvars files, which are likely to contain sentitive data, such as -# password, private keys, and other secrets. These should not be part of version -# control as they are data points which are potentially sensitive and subject -# to change depending on the environment. -*.tfvars - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json - -# Ignore CLI configuration files -.terraformrc -terraform.rc - -# Zip archive -*.zip -builds - -.DS_Store +# Local .terraform directories +**/.terraform/* + +# Terraform lockfile +.terraform.lock.hcl + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which are likely to contain sentitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Zip archive +*.zip +builds + +.DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7e4e7da..bd90148 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,31 +1,31 @@ -repos: - - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.96.1 - hooks: - - id: terraform_fmt - - id: terraform_wrapper_module_for_each - - id: terraform_docs - args: - - '--args=--lockfile=false' - - id: terraform_tflint - args: - - '--args=--only=terraform_deprecated_interpolation' - - '--args=--only=terraform_deprecated_index' - - '--args=--only=terraform_unused_declarations' - - '--args=--only=terraform_comment_syntax' - - '--args=--only=terraform_documented_outputs' - - '--args=--only=terraform_documented_variables' - - '--args=--only=terraform_typed_variables' - - '--args=--only=terraform_module_pinned_source' - - '--args=--only=terraform_naming_convention' - - '--args=--only=terraform_required_version' - - '--args=--only=terraform_required_providers' - - '--args=--only=terraform_standard_module_structure' - - '--args=--only=terraform_workspace_remote' - - id: terraform_validate - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 - hooks: - - id: check-merge-conflict - - id: end-of-file-fixer - - id: trailing-whitespace +repos: + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.96.1 + hooks: + - id: terraform_fmt + - id: terraform_wrapper_module_for_each + - id: terraform_docs + args: + - '--args=--lockfile=false' + - id: terraform_tflint + args: + - '--args=--only=terraform_deprecated_interpolation' + - '--args=--only=terraform_deprecated_index' + - '--args=--only=terraform_unused_declarations' + - '--args=--only=terraform_comment_syntax' + - '--args=--only=terraform_documented_outputs' + - '--args=--only=terraform_documented_variables' + - '--args=--only=terraform_typed_variables' + - '--args=--only=terraform_module_pinned_source' + - '--args=--only=terraform_naming_convention' + - '--args=--only=terraform_required_version' + - '--args=--only=terraform_required_providers' + - '--args=--only=terraform_standard_module_structure' + - '--args=--only=terraform_workspace_remote' + - id: terraform_validate + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-merge-conflict + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/.releaserc.json b/.releaserc.json index 66b3eef..b6d0381 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -1,45 +1,45 @@ -{ - "branches": [ - "main", - "master" - ], - "ci": false, - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/github", - { - "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", - "labels": false, - "releasedLabels": false - } - ], - [ - "@semantic-release/changelog", - { - "changelogFile": "CHANGELOG.md", - "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." - } - ], - [ - "@semantic-release/git", - { - "assets": [ - "CHANGELOG.md" - ], - "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - } - ] - ] -} +{ + "branches": [ + "main", + "master" + ], + "ci": false, + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/github", + { + "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", + "labels": false, + "releasedLabels": false + } + ], + [ + "@semantic-release/changelog", + { + "changelogFile": "CHANGELOG.md", + "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." + } + ], + [ + "@semantic-release/git", + { + "assets": [ + "CHANGELOG.md" + ], + "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ] + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 181e0ad..f9a4762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,347 +1,347 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -## [5.3.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.2.1...v5.3.0) (2025-05-01) - - -### Features - -* Support `ip_address_type` ([#135](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/135)) ([413c962](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/413c9623f9cd908bd090aa6c87b2462f814acdae)) - -## [5.2.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.2.0...v5.2.1) (2024-11-28) - - -### Bug Fixes - -* Add a way to prevent cloudwatch log group from being created ([#122](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/122)) ([ca7a071](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/ca7a0711b25124ad37400801d6ced22610e73c4f)) -* Update CI workflow versions to latest ([#123](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/123)) ([9d906dd](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/9d906dd770d18e1b08a5d110d013c5d8d11a3658)) - -## [5.2.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.3...v5.2.0) (2024-08-26) - - -### Features - -* Allow hosted zone name to be passed in separately ([#119](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/119)) ([bcd2fdb](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/bcd2fdbc9d01c8f61e23102367a8eab4f0ee152e)) - -## [5.1.3](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.2...v5.1.3) (2024-08-12) - - -### Bug Fixes - -* Remove websocket prefix from domain name output ([#118](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/118)) ([c6c0b01](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c6c0b0161052fdcacd93aab576d5ff8495bad848)) - -## [5.1.2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.1...v5.1.2) (2024-08-08) - - -### Bug Fixes - -* Correct default value check on optional maps ([#116](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/116)) ([b43e2ea](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/b43e2eabfe9b1f0b9a14383ed48bc3a04f3c3d25)) - -## [5.1.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.0...v5.1.1) (2024-08-02) - - -### Bug Fixes - -* Do not create cors_configuration when variable not provided ([#114](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/114)) ([0ed8ffe](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/0ed8ffe304c4759bfca80189be85eb506ffcdcc4)) - -## [5.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.0.0...v5.1.0) (2024-07-05) - - -### Features - -* Trigger re-deployment when API body changes ([#110](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/110)) ([909bc14](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/909bc14b4b55c0a387638d7d0a608a912f40888b)) - -## [5.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v4.0.0...v5.0.0) (2024-06-04) - - -### ⚠ BREAKING CHANGES - -* Updates to support websocket API Gateway (#54) - -### Features - -* Updates to support websocket API Gateway ([#54](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/54)) ([30c9db0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/30c9db028fe68c29f5db782c3d7bfb4f424d9ee3)) - -## [4.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.1.1...v4.0.0) (2024-03-14) - - -### ⚠ BREAKING CHANGES - -* Added creation of CW Log Group. Bump AWS provider version. (#103) - -### Features - -* Added creation of CW Log Group. Bump AWS provider version. ([#103](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/103)) ([c123558](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c12355835449be55218914677d5fb5d8f2c2f4b0)) - -## [3.1.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.1.0...v3.1.1) (2024-03-06) - - -### Bug Fixes - -* Update CI workflow versions to remove deprecated runtime warnings ([#102](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/102)) ([c052dfe](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c052dfe4c6cab30a638303f6abbd7861937adc60)) - -## [3.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.0.0...v3.1.0) (2024-02-12) - - -### Features - -* Add variable create_route to control creation of route ([#98](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/98)) ([68ad2b1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/68ad2b183a4872e29890784290b5925beee1dd29)) - -## [3.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.2...v3.0.0) (2024-02-12) - - -### ⚠ BREAKING CHANGES - -* Added the fail_on_warnings variable, bumped Terraform version to 1.0+ (#96) - -### Features - -* Added the fail_on_warnings variable, bumped Terraform version to 1.0+ ([#96](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/96)) ([26859db](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/26859db0a5d651903469f6fabeda1e341867c45d)) - -### [2.2.2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.1...v2.2.2) (2023-01-24) - - -### Bug Fixes - -* Use a version for to avoid GitHub API rate limiting on CI workflows ([#85](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/85)) ([9229fa2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/9229fa2ec7f01f9187b0ddcae3a29929e8146417)) - -### [2.2.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.0...v2.2.1) (2022-10-27) - - -### Bug Fixes - -* Update CI configuration files to use latest version ([#84](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/84)) ([13bd65e](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/13bd65e192cb39f25a7e7bd281470dd1f7c073bd)) - -## [2.2.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.1.0...v2.2.0) (2022-09-12) - - -### Features - -* Enable route_settings in default stage ([#80](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/80)) ([a13ef33](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/a13ef3308fc0b4efef53f7fefb8bc7f8012a8336)) - -## [2.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.0.0...v2.1.0) (2022-08-15) - - -### Features - -* Added API GW Authorizer IDs to outputs ([#76](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/76)) ([05da6b1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/05da6b19a0150d2d39db97968fa7214e9e4fa580)) - -## [2.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.9.0...v2.0.0) (2022-06-15) - - -### ⚠ BREAKING CHANGES - -* Upgraded AWS provider to v4 everywhere (#74) - -### Features - -* Upgraded AWS provider to v4 everywhere ([#74](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/74)) ([2f8ad61](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/2f8ad61a8668eb7559115f31e62c502ed2ea09c3)) - -## [1.9.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.8.0...v1.9.0) (2022-06-13) - - -### Features - -* Add pass-through of ownership_verification_certificate_arn to domain_name ([#72](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/72)) ([5709873](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/57098730dc48785f0836f9eb322008b054f91134)) - -## [1.8.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.7.0...v1.8.0) (2022-05-27) - - -### Features - -* Added enable_simple_responses and authorizer_credentials_arn to authorizers ([#71](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/71)) ([1467b95](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/1467b95c8309d82332857a9c2790ca25f2edc2ec)) - -## [1.7.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.6.1...v1.7.0) (2022-04-06) - - -### Features - -* Added support for ttl in authorizer resource ([#68](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/68)) ([ce1faf9](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/ce1faf96b191228bf891864f50d284078f54b0a0)) - -### [1.6.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.6.0...v1.6.1) (2022-04-01) - - -### Bug Fixes - -* Add support for passing authorization_scopes on routes with JWT authorizer ([#67](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/67)) ([c2b8d6b](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c2b8d6bd8b11fa83ccd13f3ccc74844d328f59ad)) - -## [1.6.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.1...v1.6.0) (2022-03-25) - - -### Features - -* Added support for Authorizers ([#64](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/64)) ([5cd32e0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/5cd32e0360c866c25d8a8c6300e638143335a665)) - -## [1.5.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.0...v1.5.1) (2021-11-22) - - -### Bug Fixes - -* update CI/CD process to enable auto-release workflow ([#60](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/60)) ([55f5c1d](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/55f5c1d74b4b61cf228f66c2d4a7f940e90f01b7)) - - -## [v1.5.0] - 2021-11-01 - -- feat: Add support for response_parameters in integrations ([#58](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/58)) - - - -## [v1.4.0] - 2021-09-23 - -- Feat: Add create_before_destroy lifecycle to integration resources ([#55](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/55)) - - - -## [v1.3.0] - 2021-09-16 - -- fix: Fixed output when create_api_domain_name is false ([#44](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/44)) -- chore: Fixed GH Action with terraform-docs - - - -## [v1.2.0] - 2021-08-26 - -- feat: Add support for tls_config in integrations ([#51](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/51)) -- fix: Fixed source_arn in example (fixes [#41](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/41)) - - - -## [v1.1.0] - 2021-05-25 - -- chore: Remove check boxes that don't render properly in module doc ([#40](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/40)) -- chore: update CI/CD to use stable `terraform-docs` release artifact and discoverable Apache2.0 license ([#38](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/38)) -- chore: Updated versions in README ([#37](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/37)) - - - -## [v1.0.0] - 2021-04-26 - -- feat: Shorten outputs (removing this_), added domain name to outputs ([#34](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/34)) - - - -## [v0.16.0] - 2021-04-25 - -- feat: Add support for default_route_settings ([#32](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/32)) - - - -## [v0.15.0] - 2021-04-24 - -- feat: Added support for mTLS and the ability to disable default endpoint ([#29](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/29)) -- chore: update documentation and pin `terraform_docs` version to avoid future changes ([#28](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/28)) - - - -## [v0.14.0] - 2021-03-16 - -- feat: Add support for OpenAPI definition ([#27](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/27)) - - - -## [v0.13.0] - 2021-03-10 - -- feat: Added example of step-functions integration ([#26](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/26)) - - - -## [v0.12.0] - 2021-03-09 - -- feat: Added VPC integration ([#25](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/25)) - - - -## [v0.11.0] - 2021-03-06 - -- fix: Remove workaround related to passthrough_behavior for older providers ([#24](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/24)) -- chore: align ci-cd static checks to use individual minimum Terraform versions ([#23](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/23)) -- fix: bump min supported version due to types unsupported on current ([#22](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/22)) -- chore: add ci-cd workflow for pre-commit checks ([#21](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/21)) - - - -## [v0.10.0] - 2021-02-20 - -- chore: update documentation based on latest `terraform-docs` which includes module and resource sections ([#19](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/19)) - - - -## [v0.9.0] - 2021-02-14 - -- feat: support authorization_type and authorizer_id on routes ([#17](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/17)) - - - -## [v0.8.0] - 2021-01-14 - -- feat: New useful outputs to use with route53 ([#11](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/11)) - - - -## [v0.7.0] - 2021-01-14 - -- chore: Updated example after lambda module has been updated ([#16](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/16)) -- fix: default API Gateway integration method is POST ([#14](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/14)) - - - -## [v0.6.0] - 2021-01-14 - -- fix: Integration URI is not always a lambda_arn ([#15](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/15)) - - - -## [v0.5.0] - 2020-11-24 - -- fix: Updated supported Terraform versions - - - -## [v0.4.0] - 2020-09-08 - -- feat: add VPC Links resource to allow access to private resources ([#3](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/3)) - - - -## [v0.3.0] - 2020-08-14 - -- feat: Updated version requirements for AWS provider v3 and Terraform 0.13 -- Added route53 record into example (closes [#1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/1)) -- Improved complete example - - - -## [v0.2.0] - 2020-06-07 - -- Added support for access logs - - - -## v0.1.0 - 2020-06-05 - -- Adding API Gateway module - - -[Unreleased]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.0...HEAD -[v1.5.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.4.0...v1.5.0 -[v1.4.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.3.0...v1.4.0 -[v1.3.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.2.0...v1.3.0 -[v1.2.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.1.0...v1.2.0 -[v1.1.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.0.0...v1.1.0 -[v1.0.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.16.0...v1.0.0 -[v0.16.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.15.0...v0.16.0 -[v0.15.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.14.0...v0.15.0 -[v0.14.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.13.0...v0.14.0 -[v0.13.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.12.0...v0.13.0 -[v0.12.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.11.0...v0.12.0 -[v0.11.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.10.0...v0.11.0 -[v0.10.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.9.0...v0.10.0 -[v0.9.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.8.0...v0.9.0 -[v0.8.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.7.0...v0.8.0 -[v0.7.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.6.0...v0.7.0 -[v0.6.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.5.0...v0.6.0 -[v0.5.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.4.0...v0.5.0 -[v0.4.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.3.0...v0.4.0 -[v0.3.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.2.0...v0.3.0 -[v0.2.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.1.0...v0.2.0 +# Changelog + +All notable changes to this project will be documented in this file. + +## [5.3.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.2.1...v5.3.0) (2025-05-01) + + +### Features + +* Support `ip_address_type` ([#135](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/135)) ([413c962](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/413c9623f9cd908bd090aa6c87b2462f814acdae)) + +## [5.2.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.2.0...v5.2.1) (2024-11-28) + + +### Bug Fixes + +* Add a way to prevent cloudwatch log group from being created ([#122](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/122)) ([ca7a071](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/ca7a0711b25124ad37400801d6ced22610e73c4f)) +* Update CI workflow versions to latest ([#123](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/123)) ([9d906dd](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/9d906dd770d18e1b08a5d110d013c5d8d11a3658)) + +## [5.2.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.3...v5.2.0) (2024-08-26) + + +### Features + +* Allow hosted zone name to be passed in separately ([#119](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/119)) ([bcd2fdb](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/bcd2fdbc9d01c8f61e23102367a8eab4f0ee152e)) + +## [5.1.3](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.2...v5.1.3) (2024-08-12) + + +### Bug Fixes + +* Remove websocket prefix from domain name output ([#118](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/118)) ([c6c0b01](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c6c0b0161052fdcacd93aab576d5ff8495bad848)) + +## [5.1.2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.1...v5.1.2) (2024-08-08) + + +### Bug Fixes + +* Correct default value check on optional maps ([#116](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/116)) ([b43e2ea](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/b43e2eabfe9b1f0b9a14383ed48bc3a04f3c3d25)) + +## [5.1.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.1.0...v5.1.1) (2024-08-02) + + +### Bug Fixes + +* Do not create cors_configuration when variable not provided ([#114](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/114)) ([0ed8ffe](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/0ed8ffe304c4759bfca80189be85eb506ffcdcc4)) + +## [5.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v5.0.0...v5.1.0) (2024-07-05) + + +### Features + +* Trigger re-deployment when API body changes ([#110](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/110)) ([909bc14](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/909bc14b4b55c0a387638d7d0a608a912f40888b)) + +## [5.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v4.0.0...v5.0.0) (2024-06-04) + + +### ⚠ BREAKING CHANGES + +* Updates to support websocket API Gateway (#54) + +### Features + +* Updates to support websocket API Gateway ([#54](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/54)) ([30c9db0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/30c9db028fe68c29f5db782c3d7bfb4f424d9ee3)) + +## [4.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.1.1...v4.0.0) (2024-03-14) + + +### ⚠ BREAKING CHANGES + +* Added creation of CW Log Group. Bump AWS provider version. (#103) + +### Features + +* Added creation of CW Log Group. Bump AWS provider version. ([#103](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/103)) ([c123558](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c12355835449be55218914677d5fb5d8f2c2f4b0)) + +## [3.1.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.1.0...v3.1.1) (2024-03-06) + + +### Bug Fixes + +* Update CI workflow versions to remove deprecated runtime warnings ([#102](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/102)) ([c052dfe](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c052dfe4c6cab30a638303f6abbd7861937adc60)) + +## [3.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v3.0.0...v3.1.0) (2024-02-12) + + +### Features + +* Add variable create_route to control creation of route ([#98](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/98)) ([68ad2b1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/68ad2b183a4872e29890784290b5925beee1dd29)) + +## [3.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.2...v3.0.0) (2024-02-12) + + +### ⚠ BREAKING CHANGES + +* Added the fail_on_warnings variable, bumped Terraform version to 1.0+ (#96) + +### Features + +* Added the fail_on_warnings variable, bumped Terraform version to 1.0+ ([#96](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/96)) ([26859db](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/26859db0a5d651903469f6fabeda1e341867c45d)) + +### [2.2.2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.1...v2.2.2) (2023-01-24) + + +### Bug Fixes + +* Use a version for to avoid GitHub API rate limiting on CI workflows ([#85](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/85)) ([9229fa2](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/9229fa2ec7f01f9187b0ddcae3a29929e8146417)) + +### [2.2.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.2.0...v2.2.1) (2022-10-27) + + +### Bug Fixes + +* Update CI configuration files to use latest version ([#84](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/84)) ([13bd65e](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/13bd65e192cb39f25a7e7bd281470dd1f7c073bd)) + +## [2.2.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.1.0...v2.2.0) (2022-09-12) + + +### Features + +* Enable route_settings in default stage ([#80](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/80)) ([a13ef33](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/a13ef3308fc0b4efef53f7fefb8bc7f8012a8336)) + +## [2.1.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v2.0.0...v2.1.0) (2022-08-15) + + +### Features + +* Added API GW Authorizer IDs to outputs ([#76](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/76)) ([05da6b1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/05da6b19a0150d2d39db97968fa7214e9e4fa580)) + +## [2.0.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.9.0...v2.0.0) (2022-06-15) + + +### ⚠ BREAKING CHANGES + +* Upgraded AWS provider to v4 everywhere (#74) + +### Features + +* Upgraded AWS provider to v4 everywhere ([#74](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/74)) ([2f8ad61](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/2f8ad61a8668eb7559115f31e62c502ed2ea09c3)) + +## [1.9.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.8.0...v1.9.0) (2022-06-13) + + +### Features + +* Add pass-through of ownership_verification_certificate_arn to domain_name ([#72](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/72)) ([5709873](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/57098730dc48785f0836f9eb322008b054f91134)) + +## [1.8.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.7.0...v1.8.0) (2022-05-27) + + +### Features + +* Added enable_simple_responses and authorizer_credentials_arn to authorizers ([#71](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/71)) ([1467b95](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/1467b95c8309d82332857a9c2790ca25f2edc2ec)) + +## [1.7.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.6.1...v1.7.0) (2022-04-06) + + +### Features + +* Added support for ttl in authorizer resource ([#68](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/68)) ([ce1faf9](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/ce1faf96b191228bf891864f50d284078f54b0a0)) + +### [1.6.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.6.0...v1.6.1) (2022-04-01) + + +### Bug Fixes + +* Add support for passing authorization_scopes on routes with JWT authorizer ([#67](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/67)) ([c2b8d6b](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/c2b8d6bd8b11fa83ccd13f3ccc74844d328f59ad)) + +## [1.6.0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.1...v1.6.0) (2022-03-25) + + +### Features + +* Added support for Authorizers ([#64](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/64)) ([5cd32e0](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/5cd32e0360c866c25d8a8c6300e638143335a665)) + +## [1.5.1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.0...v1.5.1) (2021-11-22) + + +### Bug Fixes + +* update CI/CD process to enable auto-release workflow ([#60](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/60)) ([55f5c1d](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/commit/55f5c1d74b4b61cf228f66c2d4a7f940e90f01b7)) + + +## [v1.5.0] - 2021-11-01 + +- feat: Add support for response_parameters in integrations ([#58](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/58)) + + + +## [v1.4.0] - 2021-09-23 + +- Feat: Add create_before_destroy lifecycle to integration resources ([#55](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/55)) + + + +## [v1.3.0] - 2021-09-16 + +- fix: Fixed output when create_api_domain_name is false ([#44](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/44)) +- chore: Fixed GH Action with terraform-docs + + + +## [v1.2.0] - 2021-08-26 + +- feat: Add support for tls_config in integrations ([#51](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/51)) +- fix: Fixed source_arn in example (fixes [#41](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/41)) + + + +## [v1.1.0] - 2021-05-25 + +- chore: Remove check boxes that don't render properly in module doc ([#40](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/40)) +- chore: update CI/CD to use stable `terraform-docs` release artifact and discoverable Apache2.0 license ([#38](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/38)) +- chore: Updated versions in README ([#37](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/37)) + + + +## [v1.0.0] - 2021-04-26 + +- feat: Shorten outputs (removing this_), added domain name to outputs ([#34](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/34)) + + + +## [v0.16.0] - 2021-04-25 + +- feat: Add support for default_route_settings ([#32](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/32)) + + + +## [v0.15.0] - 2021-04-24 + +- feat: Added support for mTLS and the ability to disable default endpoint ([#29](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/29)) +- chore: update documentation and pin `terraform_docs` version to avoid future changes ([#28](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/28)) + + + +## [v0.14.0] - 2021-03-16 + +- feat: Add support for OpenAPI definition ([#27](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/27)) + + + +## [v0.13.0] - 2021-03-10 + +- feat: Added example of step-functions integration ([#26](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/26)) + + + +## [v0.12.0] - 2021-03-09 + +- feat: Added VPC integration ([#25](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/25)) + + + +## [v0.11.0] - 2021-03-06 + +- fix: Remove workaround related to passthrough_behavior for older providers ([#24](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/24)) +- chore: align ci-cd static checks to use individual minimum Terraform versions ([#23](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/23)) +- fix: bump min supported version due to types unsupported on current ([#22](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/22)) +- chore: add ci-cd workflow for pre-commit checks ([#21](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/21)) + + + +## [v0.10.0] - 2021-02-20 + +- chore: update documentation based on latest `terraform-docs` which includes module and resource sections ([#19](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/19)) + + + +## [v0.9.0] - 2021-02-14 + +- feat: support authorization_type and authorizer_id on routes ([#17](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/17)) + + + +## [v0.8.0] - 2021-01-14 + +- feat: New useful outputs to use with route53 ([#11](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/11)) + + + +## [v0.7.0] - 2021-01-14 + +- chore: Updated example after lambda module has been updated ([#16](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/16)) +- fix: default API Gateway integration method is POST ([#14](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/14)) + + + +## [v0.6.0] - 2021-01-14 + +- fix: Integration URI is not always a lambda_arn ([#15](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/15)) + + + +## [v0.5.0] - 2020-11-24 + +- fix: Updated supported Terraform versions + + + +## [v0.4.0] - 2020-09-08 + +- feat: add VPC Links resource to allow access to private resources ([#3](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/3)) + + + +## [v0.3.0] - 2020-08-14 + +- feat: Updated version requirements for AWS provider v3 and Terraform 0.13 +- Added route53 record into example (closes [#1](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/issues/1)) +- Improved complete example + + + +## [v0.2.0] - 2020-06-07 + +- Added support for access logs + + + +## v0.1.0 - 2020-06-05 + +- Adding API Gateway module + + +[Unreleased]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.5.0...HEAD +[v1.5.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.4.0...v1.5.0 +[v1.4.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.3.0...v1.4.0 +[v1.3.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.2.0...v1.3.0 +[v1.2.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.1.0...v1.2.0 +[v1.1.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v1.0.0...v1.1.0 +[v1.0.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.16.0...v1.0.0 +[v0.16.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.15.0...v0.16.0 +[v0.15.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.14.0...v0.15.0 +[v0.14.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.13.0...v0.14.0 +[v0.13.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.12.0...v0.13.0 +[v0.12.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.11.0...v0.12.0 +[v0.11.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.10.0...v0.11.0 +[v0.10.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.9.0...v0.10.0 +[v0.9.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.8.0...v0.9.0 +[v0.8.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.7.0...v0.8.0 +[v0.7.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.6.0...v0.7.0 +[v0.6.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.5.0...v0.6.0 +[v0.5.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.4.0...v0.5.0 +[v0.4.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.3.0...v0.4.0 +[v0.3.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.2.0...v0.3.0 +[v0.2.0]: https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/compare/v0.1.0...v0.2.0 diff --git a/LICENSE b/LICENSE index d9a10c0..7cd40e5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,176 +1,176 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index 1a5fdd3..18a7c41 100644 --- a/README.md +++ b/README.md @@ -1,176 +1,176 @@ -# AWS API Gateway v2 (HTTP/Websocket) Terraform module - -Terraform module which creates API Gateway v2 resources with HTTP/Websocket capabilities. - -This Terraform module is part of [serverless.tf framework](https://serverless.tf), which aims to simplify all operations when working with the serverless in Terraform. - -## Usage - -### HTTP API Gateway - -```hcl -module "api_gateway" { - source = "terraform-aws-modules/apigateway-v2/aws" - - name = "dev-http" - description = "My awesome HTTP API Gateway" - protocol_type = "HTTP" - - cors_configuration = { - allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] - allow_methods = ["*"] - allow_origins = ["*"] - } - - # Custom domain - domain_name = "terraform-aws-modules.modules.tf" - - # Access logs - stage_access_log_settings = { - create_log_group = true - log_group_retention_in_days = 7 - format = jsonencode({ - context = { - domainName = "$context.domainName" - integrationErrorMessage = "$context.integrationErrorMessage" - protocol = "$context.protocol" - requestId = "$context.requestId" - requestTime = "$context.requestTime" - responseLength = "$context.responseLength" - routeKey = "$context.routeKey" - stage = "$context.stage" - status = "$context.status" - error = { - message = "$context.error.message" - responseType = "$context.error.responseType" - } - identity = { - sourceIP = "$context.identity.sourceIp" - } - integration = { - error = "$context.integration.error" - integrationStatus = "$context.integration.integrationStatus" - } - } - }) - } - - # Authorizer(s) - authorizers = { - "azure" = { - authorizer_type = "JWT" - identity_sources = ["$request.header.Authorization"] - name = "azure-auth" - jwt_configuration = { - audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] - issuer = "https://sts.windows.net/aaee026e-8f37-410e-8869-72d9154873e4/" - } - } - } - - # Routes & Integration(s) - routes = { - "POST /" = { - integration = { - uri = "arn:aws:lambda:eu-west-1:052235179155:function:my-function" - payload_format_version = "2.0" - timeout_milliseconds = 12000 - } - } - - "GET /some-route-with-authorizer" = { - authorizer_key = "azure" - - integration = { - type = "HTTP_PROXY" - uri = "some url" - } - } - - "$default" = { - integration = { - uri = "arn:aws:lambda:eu-west-1:052235179155:function:my-default-function" - } - } - } - - tags = { - Environment = "dev" - Terraform = "true" - } -} -``` - -## Multiple Subdomains - -API Gateway v2 supports wildcard custom domains which allow users to map multiple subdomains to the same API Gateway. This is useful when you have multiple customers and you want to provide them with a custom domain for their API endpoint and possibly use that for header based routing/rules. - -```hcl -module "api_gateway" { - source = "terraform-aws-modules/apigateway-v2/aws" - - ... - domain_name = "*.mydomain.com" - subdomains = ["customer1", "customer2"] - ... -} -``` - -This will create records that allow users to access the API Gateway using the following subdomains: -- `customer1.mydomain.com` -- `customer2.mydomain.com` - -## Specific Hosted Zone - -If you want to create the domain name in a specific hosted zone, you can use the `hosted_zone_name` input parameter: - -```hcl -module "api_gateway" { - source = "terraform-aws-modules/apigateway-v2/aws" - - ... - hosted_zone_name = "api.mydomain.com" - domain_name = "prod.api.mydomain.com" - ... -} -``` - -## Conditional Creation - -The following values are provided to toggle on/off creation of the associated resources as desired: - -```hcl -module "api_gateway" { - source = "terraform-aws-modules/apigateway-v2/aws" - - # Disable creation of the API and all resources - create = false - - # Disable creation of the domain name and API mapping - create_domain_name = false - - # Disable creation of Route53 alias record(s) for the custom domain - create_domain_records = false - - # Disable creation of the ACM certificate for the custom domain - create_certificate = false - - # Disable creation of the routes and integrations - create_routes_and_integrations = false - - # Disable creation of the stage - create_stage = false - - # ... omitted -} -``` - -## Examples - -- [Complete HTTP](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/complete-http) - Create API Gateway, authorizer, domain name, stage and other resources in various combinations -- [HTTP with VPC Link](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/vpc-link-http) - Create API Gateway with VPC link and integration with resources in VPC (eg. ALB) -- [Websocket](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/websocket) - Create Websocket API - +# AWS API Gateway v2 (HTTP/Websocket) Terraform module + +Terraform module which creates API Gateway v2 resources with HTTP/Websocket capabilities. + +This Terraform module is part of [serverless.tf framework](https://serverless.tf), which aims to simplify all operations when working with the serverless in Terraform. + +## Usage + +### HTTP API Gateway + +```hcl +module "api_gateway" { + source = "terraform-aws-modules/apigateway-v2/aws" + + name = "dev-http" + description = "My awesome HTTP API Gateway" + protocol_type = "HTTP" + + cors_configuration = { + allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] + allow_methods = ["*"] + allow_origins = ["*"] + } + + # Custom domain + domain_name = "terraform-aws-modules.modules.tf" + + # Access logs + stage_access_log_settings = { + create_log_group = true + log_group_retention_in_days = 7 + format = jsonencode({ + context = { + domainName = "$context.domainName" + integrationErrorMessage = "$context.integrationErrorMessage" + protocol = "$context.protocol" + requestId = "$context.requestId" + requestTime = "$context.requestTime" + responseLength = "$context.responseLength" + routeKey = "$context.routeKey" + stage = "$context.stage" + status = "$context.status" + error = { + message = "$context.error.message" + responseType = "$context.error.responseType" + } + identity = { + sourceIP = "$context.identity.sourceIp" + } + integration = { + error = "$context.integration.error" + integrationStatus = "$context.integration.integrationStatus" + } + } + }) + } + + # Authorizer(s) + authorizers = { + "azure" = { + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = "azure-auth" + jwt_configuration = { + audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] + issuer = "https://sts.windows.net/aaee026e-8f37-410e-8869-72d9154873e4/" + } + } + } + + # Routes & Integration(s) + routes = { + "POST /" = { + integration = { + uri = "arn:aws:lambda:eu-west-1:052235179155:function:my-function" + payload_format_version = "2.0" + timeout_milliseconds = 12000 + } + } + + "GET /some-route-with-authorizer" = { + authorizer_key = "azure" + + integration = { + type = "HTTP_PROXY" + uri = "some url" + } + } + + "$default" = { + integration = { + uri = "arn:aws:lambda:eu-west-1:052235179155:function:my-default-function" + } + } + } + + tags = { + Environment = "dev" + Terraform = "true" + } +} +``` + +## Multiple Subdomains + +API Gateway v2 supports wildcard custom domains which allow users to map multiple subdomains to the same API Gateway. This is useful when you have multiple customers and you want to provide them with a custom domain for their API endpoint and possibly use that for header based routing/rules. + +```hcl +module "api_gateway" { + source = "terraform-aws-modules/apigateway-v2/aws" + + ... + domain_name = "*.mydomain.com" + subdomains = ["customer1", "customer2"] + ... +} +``` + +This will create records that allow users to access the API Gateway using the following subdomains: +- `customer1.mydomain.com` +- `customer2.mydomain.com` + +## Specific Hosted Zone + +If you want to create the domain name in a specific hosted zone, you can use the `hosted_zone_name` input parameter: + +```hcl +module "api_gateway" { + source = "terraform-aws-modules/apigateway-v2/aws" + + ... + hosted_zone_name = "api.mydomain.com" + domain_name = "prod.api.mydomain.com" + ... +} +``` + +## Conditional Creation + +The following values are provided to toggle on/off creation of the associated resources as desired: + +```hcl +module "api_gateway" { + source = "terraform-aws-modules/apigateway-v2/aws" + + # Disable creation of the API and all resources + create = false + + # Disable creation of the domain name and API mapping + create_domain_name = false + + # Disable creation of Route53 alias record(s) for the custom domain + create_domain_records = false + + # Disable creation of the ACM certificate for the custom domain + create_certificate = false + + # Disable creation of the routes and integrations + create_routes_and_integrations = false + + # Disable creation of the stage + create_stage = false + + # ... omitted +} +``` + +## Examples + +- [Complete HTTP](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/complete-http) - Create API Gateway, authorizer, domain name, stage and other resources in various combinations +- [HTTP with VPC Link](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/vpc-link-http) - Create API Gateway with VPC link and integration with resources in VPC (eg. ALB) +- [Websocket](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/examples/websocket) - Create Websocket API + ## Requirements @@ -238,7 +238,7 @@ module "api_gateway" { | [ip\_address\_type](#input\_ip\_address\_type) | The IP address types that can invoke the API. Valid values: ipv4, dualstack. Use ipv4 to allow only IPv4 addresses to invoke your API, or use dualstack to allow both IPv4 and IPv6 addresses to invoke your API. Defaults to ipv4. | `string` | `null` | no | | [mutual\_tls\_authentication](#input\_mutual\_tls\_authentication) | The mutual TLS authentication configuration for the domain name | `map(string)` | `{}` | no | | [name](#input\_name) | The name of the API. Must be less than or equal to 128 characters in length | `string` | `""` | no | -| [private\_zone](#input\_private\_zone) | Whether the hosted zone is private or not. `false` for public hosted zone. `true` for private hosted zone. | `bool` | `false` | no | +| [private\_zone](#input\_private\_zone) | Whether the hosted zone is private or not | `bool` | `false` | no | | [protocol\_type](#input\_protocol\_type) | The API protocol. Valid values: `HTTP`, `WEBSOCKET` | `string` | `"HTTP"` | no | | [route\_key](#input\_route\_key) | Part of quick create. Specifies any route key. Applicable for HTTP APIs | `string` | `null` | no | | [route\_selection\_expression](#input\_route\_selection\_expression) | The route selection expression for the API. Defaults to `$request.method $request.path` | `string` | `null` | no | @@ -283,14 +283,14 @@ module "api_gateway" { | [stage\_id](#output\_stage\_id) | The stage identifier | | [stage\_invoke\_url](#output\_stage\_invoke\_url) | The URL to invoke the API pointing to the stage | | [vpc\_links](#output\_vpc\_links) | Map of VPC links created and their attributes | - - -## Authors - -Module managed by [Anton Babenko](https://github.com/antonbabenko). Check out [serverless.tf](https://serverless.tf) to learn more about doing serverless with Terraform. - -Please reach out to [Betajob](https://www.betajob.com/) if you are looking for commercial support for your Terraform, AWS, or serverless project. - -## License - -Apache 2 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/LICENSE) for full details. + + +## Authors + +Module managed by [Anton Babenko](https://github.com/antonbabenko). Check out [serverless.tf](https://serverless.tf) to learn more about doing serverless with Terraform. + +Please reach out to [Betajob](https://www.betajob.com/) if you are looking for commercial support for your Terraform, AWS, or serverless project. + +## License + +Apache 2 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/tree/master/LICENSE) for full details. diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index abe198b..3223405 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -1,215 +1,215 @@ -# Upgrade from v4.x to v5.x - -Please consult the `examples` directory for reference example configurations. If you find a bug, please open an issue with supporting configuration to reproduce. - -## List of backwards incompatible changes - -- Minimum supported Terraform version increased to `v1.3` to support Terraform state `moved` blocks as well as other advanced features -- The `apigatewayv2_` and `default_apigatewayv2_` prefixes has been removed from the output names -- When a custom domain is used, the execution endpoint is disabled automatically; this is to ensure that requests are sent via the custom domain -- For `authorizers`, the `audience` and `issuer` properties are now nested under `jwt_configuration` to better match the upstream API - -## Additional changes - -- Minimum supported Terraform AWS provider raised to `v5.37.0` to support recent bug fixes in the provider -- Default values for `api_key_selection_expression`, `route_selection_expression` variables set to `null` (still matches prior value v4.x version but is set as `null` now) -- The input data structure for `routes` (was `integrations`) has been updated and now uses optional inputs - -### Added - - - Support for creating a websocket API endpoint - - Support for creating Route53 alias records for custom domain names w/ support for multiple sub-domains using a wildcard API Gateway custom domain name - - Support for creating ACM certificate for custom domain - - Support for automatically deploying the stage when updates have been made (for Websocket, HTTP is always auto-deployed by the API) - -### Modified - - - Stage access log group settings are now embedded into the `stage_access_log_settings` variable - - API mapping is created automatically when using a custom domain - - Default values of 500 and 1000 have been set for `throttling_burst_limit` and `throttling_rate_limit` respectively to ensure users do not face errors when deploying APIs for the first time and not configuring these - - Default values for the log group name (`"/aws/apigateway/${var.name}/${var.stage_name}"`) and retention period (`30`) have been provided for the stage access logs log group - -### Removed - - - None - -### Variable and output changes - -1. Removed variables: - - - `create_api_gateway` - - `create_default_stage_api_mapping` - - `create_default_stage_access_log_group` -> replaced by `create_log_group` set within `stage_access_log_settings` - - `default_stage_access_log_*` -> replaced by setting values within `stage_access_log_settings` - - `create_vpc_link` - - `default_stage_access_log_destination_arn` - - `domain_name_tags` - -2. Renamed variables: - - - `integrations` -> `routes` - - `create_default_stage` -> `create_stage` - - `create_api_domain_name` -> `create_domain_name` - - `default_route_settings` -> `stage_default_route_settings` - - `default_stage_tags` -> `stage_tags` - -3. Added variables: - - - `create_domain_name` - - `create_domain_records` - - `subdomains` - - `create_certificate` - - `stage_access_log_settings` - - `stage_client_certificate_id` - - `stage_description` - - `stage_name` - - `stage_variables` - - `deploy_stage` - -4. Removed outputs: - - - `default_apigatewayv2_stage_domain_name` - - `aws_apigatewayv2_api_mapping` - - `apigatewayv2_vpc_link_id` -> replaced by `vpc_links` - - `apigatewayv2_vpc_link_arn` -> replaced by `vpc_links` - - `apigatewayv2_authorizer_id` -> replaced by `authorizers` - -5. Renamed outputs: - - - `apigatewayv2_api_` -> prefix replaced with `api_` - - `default_apigatewayv2_stage_` prefix replaced with `stage_` - - `apigatewayv2_domain_` prefix replaced with `domain_` - -6. Added outputs: - - - `acm_certificate_arn` - - `integrations` - - `routes` - - `stage_access_logs_cloudwatch_log_group_name` - - `stage_access_logs_cloudwatch_log_group_arn` - -## Upgrade Migrations - -### Diff of Before (v4.0) vs After (v5.0) - -```diff - module "apigateway_v2" { - source = "terraform-aws-modules/apigateway-v2/aws" -- version = "~> 4.0" -+ version = "~> 5.0" - -- create_default_stage_access_log_group = true -- default_stage_access_log_format = "$context.identity.sourceIp" -+ stage_access_log_settings = { -+ create_log_group = true -+ format = "$context.identity.sourceIp" -+ } - - authorizers = { - "cognito" = { - authorizer_type = "JWT" - identity_sources = "$request.header.Authorization" - name = "cognito" - -- audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] -- issuer = "https://${aws_cognito_user_pool.this.endpoint}" - jwt_configuration = { -+ audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] -+ issuer = "https://${aws_cognito_user_pool.this.endpoint}" - } - } - } - -- integrations = { -+ routes = { - "POST /start-step-function" = { -- integration_type = "AWS_PROXY" -- integration_subtype = "StepFunctions-StartExecution" -- credentials_arn = module.step_function.role_arn - -- request_parameters = jsonencode({ -- StateMachineArn = module.step_function.state_machine_arn -- }) - -- payload_format_version = "1.0" -- timeout_milliseconds = 12000 - -+ integration = { -+ type = "AWS_PROXY" -+ subtype = "StepFunctions-StartExecution" -+ credentials_arn = module.step_function.role_arn - -+ request_parameters = { -+ StateMachineArn = module.step_function.state_machine_arn -+ } - -+ payload_format_version = "1.0" -+ timeout_milliseconds = 12000 -+ } - } - - "GET /some-route-with-authorizer-and-scope" = { -- lambda_arn = module.lambda_function.lambda_function_arn -- payload_format_version = "2.0" -- authorization_type = "JWT" -- authorizer_key = "cognito" -- authorization_scopes = "tf/something.relevant.read,tf/something.relevant.write" - -+ authorization_type = "JWT" -+ authorizer_key = "cognito" -+ authorization_scopes = ["tf/something.relevant.read", "tf/something.relevant.write"] - -+ integration = { -+ uri = module.lambda_function.lambda_function_arn -+ payload_format_version = "2.0" -+ } - } - - "$default" = { -- lambda_arn = module.lambda_function.lambda_function_arn -- tls_config = jsonencode({ -- server_name_to_verify = local.domain_name -- }) - -- response_parameters = jsonencode([ -- { -- status_code = 500 -- mappings = { -- "append:header.header1" = "$context.requestId" -- "overwrite:statuscode" = "403" -- } -- }, -- { -- status_code = 404 -- mappings = { -- "append:header.error" = "$stageVariables.environmentId" -- } -- } -- ]) - -+ integration = { -+ uri = module.lambda_function.lambda_function_arn -+ tls_config = jsonencode({ -+ server_name_to_verify = local.domain_name -+ }) - -+ response_parameters = [ -+ { -+ status_code = 500 -+ mappings = { -+ "append:header.header1" = "$context.requestId" -+ "overwrite:statuscode" = "403" -+ } -+ }, -+ { -+ status_code = 404 -+ mappings = { -+ "append:header.error" = "$stageVariables.environmentId" -+ } -+ } -+ ] -+ } - } - } -} -``` +# Upgrade from v4.x to v5.x + +Please consult the `examples` directory for reference example configurations. If you find a bug, please open an issue with supporting configuration to reproduce. + +## List of backwards incompatible changes + +- Minimum supported Terraform version increased to `v1.3` to support Terraform state `moved` blocks as well as other advanced features +- The `apigatewayv2_` and `default_apigatewayv2_` prefixes has been removed from the output names +- When a custom domain is used, the execution endpoint is disabled automatically; this is to ensure that requests are sent via the custom domain +- For `authorizers`, the `audience` and `issuer` properties are now nested under `jwt_configuration` to better match the upstream API + +## Additional changes + +- Minimum supported Terraform AWS provider raised to `v5.37.0` to support recent bug fixes in the provider +- Default values for `api_key_selection_expression`, `route_selection_expression` variables set to `null` (still matches prior value v4.x version but is set as `null` now) +- The input data structure for `routes` (was `integrations`) has been updated and now uses optional inputs + +### Added + + - Support for creating a websocket API endpoint + - Support for creating Route53 alias records for custom domain names w/ support for multiple sub-domains using a wildcard API Gateway custom domain name + - Support for creating ACM certificate for custom domain + - Support for automatically deploying the stage when updates have been made (for Websocket, HTTP is always auto-deployed by the API) + +### Modified + + - Stage access log group settings are now embedded into the `stage_access_log_settings` variable + - API mapping is created automatically when using a custom domain + - Default values of 500 and 1000 have been set for `throttling_burst_limit` and `throttling_rate_limit` respectively to ensure users do not face errors when deploying APIs for the first time and not configuring these + - Default values for the log group name (`"/aws/apigateway/${var.name}/${var.stage_name}"`) and retention period (`30`) have been provided for the stage access logs log group + +### Removed + + - None + +### Variable and output changes + +1. Removed variables: + + - `create_api_gateway` + - `create_default_stage_api_mapping` + - `create_default_stage_access_log_group` -> replaced by `create_log_group` set within `stage_access_log_settings` + - `default_stage_access_log_*` -> replaced by setting values within `stage_access_log_settings` + - `create_vpc_link` + - `default_stage_access_log_destination_arn` + - `domain_name_tags` + +2. Renamed variables: + + - `integrations` -> `routes` + - `create_default_stage` -> `create_stage` + - `create_api_domain_name` -> `create_domain_name` + - `default_route_settings` -> `stage_default_route_settings` + - `default_stage_tags` -> `stage_tags` + +3. Added variables: + + - `create_domain_name` + - `create_domain_records` + - `subdomains` + - `create_certificate` + - `stage_access_log_settings` + - `stage_client_certificate_id` + - `stage_description` + - `stage_name` + - `stage_variables` + - `deploy_stage` + +4. Removed outputs: + + - `default_apigatewayv2_stage_domain_name` + - `aws_apigatewayv2_api_mapping` + - `apigatewayv2_vpc_link_id` -> replaced by `vpc_links` + - `apigatewayv2_vpc_link_arn` -> replaced by `vpc_links` + - `apigatewayv2_authorizer_id` -> replaced by `authorizers` + +5. Renamed outputs: + + - `apigatewayv2_api_` -> prefix replaced with `api_` + - `default_apigatewayv2_stage_` prefix replaced with `stage_` + - `apigatewayv2_domain_` prefix replaced with `domain_` + +6. Added outputs: + + - `acm_certificate_arn` + - `integrations` + - `routes` + - `stage_access_logs_cloudwatch_log_group_name` + - `stage_access_logs_cloudwatch_log_group_arn` + +## Upgrade Migrations + +### Diff of Before (v4.0) vs After (v5.0) + +```diff + module "apigateway_v2" { + source = "terraform-aws-modules/apigateway-v2/aws" +- version = "~> 4.0" ++ version = "~> 5.0" + +- create_default_stage_access_log_group = true +- default_stage_access_log_format = "$context.identity.sourceIp" ++ stage_access_log_settings = { ++ create_log_group = true ++ format = "$context.identity.sourceIp" ++ } + + authorizers = { + "cognito" = { + authorizer_type = "JWT" + identity_sources = "$request.header.Authorization" + name = "cognito" + +- audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] +- issuer = "https://${aws_cognito_user_pool.this.endpoint}" + jwt_configuration = { ++ audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] ++ issuer = "https://${aws_cognito_user_pool.this.endpoint}" + } + } + } + +- integrations = { ++ routes = { + "POST /start-step-function" = { +- integration_type = "AWS_PROXY" +- integration_subtype = "StepFunctions-StartExecution" +- credentials_arn = module.step_function.role_arn + +- request_parameters = jsonencode({ +- StateMachineArn = module.step_function.state_machine_arn +- }) + +- payload_format_version = "1.0" +- timeout_milliseconds = 12000 + ++ integration = { ++ type = "AWS_PROXY" ++ subtype = "StepFunctions-StartExecution" ++ credentials_arn = module.step_function.role_arn + ++ request_parameters = { ++ StateMachineArn = module.step_function.state_machine_arn ++ } + ++ payload_format_version = "1.0" ++ timeout_milliseconds = 12000 ++ } + } + + "GET /some-route-with-authorizer-and-scope" = { +- lambda_arn = module.lambda_function.lambda_function_arn +- payload_format_version = "2.0" +- authorization_type = "JWT" +- authorizer_key = "cognito" +- authorization_scopes = "tf/something.relevant.read,tf/something.relevant.write" + ++ authorization_type = "JWT" ++ authorizer_key = "cognito" ++ authorization_scopes = ["tf/something.relevant.read", "tf/something.relevant.write"] + ++ integration = { ++ uri = module.lambda_function.lambda_function_arn ++ payload_format_version = "2.0" ++ } + } + + "$default" = { +- lambda_arn = module.lambda_function.lambda_function_arn +- tls_config = jsonencode({ +- server_name_to_verify = local.domain_name +- }) + +- response_parameters = jsonencode([ +- { +- status_code = 500 +- mappings = { +- "append:header.header1" = "$context.requestId" +- "overwrite:statuscode" = "403" +- } +- }, +- { +- status_code = 404 +- mappings = { +- "append:header.error" = "$stageVariables.environmentId" +- } +- } +- ]) + ++ integration = { ++ uri = module.lambda_function.lambda_function_arn ++ tls_config = jsonencode({ ++ server_name_to_verify = local.domain_name ++ }) + ++ response_parameters = [ ++ { ++ status_code = 500 ++ mappings = { ++ "append:header.header1" = "$context.requestId" ++ "overwrite:statuscode" = "403" ++ } ++ }, ++ { ++ status_code = 404 ++ mappings = { ++ "append:header.error" = "$stageVariables.environmentId" ++ } ++ } ++ ] ++ } + } + } +} +``` diff --git a/examples/README.md b/examples/README.md index f417c0a..21c03af 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,8 +1,8 @@ -# Examples - -Please note - the examples provided serve two primary means: - -1. Show users working examples of the various ways in which the module can be configured and features supported -2. A means of testing/validating module changes - -Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc. +# Examples + +Please note - the examples provided serve two primary means: + +1. Show users working examples of the various ways in which the module can be configured and features supported +2. A means of testing/validating module changes + +Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc. diff --git a/examples/complete-http/README.md b/examples/complete-http/README.md index 082e8f0..782e1b4 100644 --- a/examples/complete-http/README.md +++ b/examples/complete-http/README.md @@ -1,19 +1,19 @@ -# Complete AWS API Gateway (HTTP) examples - -Configuration in this directory creates AWS API Gateway with Domain Name, ACM Certificate, and integrates it with Lambda and Step Function and shows the variety of supported features. - -## Usage - -To run this example you need to execute: - -```bash -$ terraform init -$ terraform plan -$ terraform apply -``` - -Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. - +# Complete AWS API Gateway (HTTP) examples + +Configuration in this directory creates AWS API Gateway with Domain Name, ACM Certificate, and integrates it with Lambda and Step Function and shows the variety of supported features. + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. + ## Requirements @@ -90,6 +90,6 @@ Note that this example may create resources which cost money. Run `terraform des | [stage\_invoke\_url](#output\_stage\_invoke\_url) | The URL to invoke the API pointing to the stage | | [test\_curl\_command](#output\_test\_curl\_command) | Curl command to test API endpoint using mTLS | | [vpc\_links](#output\_vpc\_links) | Map of VPC links created and their attributes | - - -Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). + + +Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). diff --git a/examples/complete-http/api.yaml b/examples/complete-http/api.yaml index d36197b..09fb532 100644 --- a/examples/complete-http/api.yaml +++ b/examples/complete-http/api.yaml @@ -1,22 +1,22 @@ -openapi: "3.0.1" -info: - version: 0.0.1 - description: My awesome API -paths: - /debug: - get: - operationId: getDebug - responses: - default: - description: "Default response for GET /debug" - x-amazon-apigateway-integration: - $ref: '#/components/x-amazon-apigateway-integrations/debug' - -components: - x-amazon-apigateway-integrations: - debug: - type: AWS_PROXY - httpMethod: GET - uri: "${example_function_arn}" - payloadFormatVersion: "2.0" - connectionType: INTERNET +openapi: "3.0.1" +info: + version: 0.0.1 + description: My awesome API +paths: + /debug: + get: + operationId: getDebug + responses: + default: + description: "Default response for GET /debug" + x-amazon-apigateway-integration: + $ref: '#/components/x-amazon-apigateway-integrations/debug' + +components: + x-amazon-apigateway-integrations: + debug: + type: AWS_PROXY + httpMethod: GET + uri: "${example_function_arn}" + payloadFormatVersion: "2.0" + connectionType: INTERNET diff --git a/examples/complete-http/main.tf b/examples/complete-http/main.tf index 07cd360..80770eb 100644 --- a/examples/complete-http/main.tf +++ b/examples/complete-http/main.tf @@ -1,351 +1,351 @@ -provider "aws" { - region = local.region -} - -locals { - name = "ex-${basename(path.cwd)}" - region = "eu-west-1" - - tags = { - Example = local.name - GithubRepo = "terraform-aws-apigateway-v2" - GithubOrg = "terraform-aws-modules" - } -} - -################################################################################ -# API Gateway Module -################################################################################ - -module "api_gateway" { - source = "../../" - - # API - body = templatefile("api.yaml", { - example_function_arn = module.lambda_function.lambda_function_arn - }) - - cors_configuration = { - allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] - allow_methods = ["*"] - allow_origins = ["*"] - } - - description = "My awesome HTTP API Gateway" - fail_on_warnings = false - name = local.name - - # Authorizer(s) - authorizers = { - cognito = { - authorizer_type = "JWT" - identity_sources = ["$request.header.Authorization"] - name = "cognito" - jwt_configuration = { - audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] - issuer = "https://${aws_cognito_user_pool.this.endpoint}" - } - } - } - - # Domain Name - domain_name = var.domain_name - create_domain_records = true - create_certificate = true - - mutual_tls_authentication = { - truststore_uri = "s3://${module.s3_bucket.s3_bucket_id}/${aws_s3_object.this.id}" - truststore_version = aws_s3_object.this.version_id - } - - # Routes & Integration(s) - routes = { - "ANY /" = { - detailed_metrics_enabled = false - - integration = { - uri = module.lambda_function.lambda_function_arn - payload_format_version = "2.0" - timeout_milliseconds = 12000 - } - } - - "GET /some-route" = { - authorization_type = "JWT" - authorizer_id = aws_apigatewayv2_authorizer.external.id - throttling_rate_limit = 80 - throttling_burst_limit = 40 - detailed_metrics_enabled = true - - integration = { - uri = module.lambda_function.lambda_function_arn - payload_format_version = "2.0" - } - } - - "GET /some-route-with-authorizer" = { - authorization_type = "JWT" - authorizer_key = "cognito" - - integration = { - uri = module.lambda_function.lambda_function_arn - payload_format_version = "2.0" - } - } - - "GET /some-route-with-authorizer-and-scope" = { - authorization_type = "JWT" - authorizer_key = "cognito" - authorization_scopes = ["user.id", "user.email"] - - integration = { - uri = module.lambda_function.lambda_function_arn - payload_format_version = "2.0" - } - } - - "POST /start-step-function" = { - integration = { - type = "AWS_PROXY" - subtype = "StepFunctions-StartExecution" - credentials_arn = module.step_function.role_arn - - # Note: jsonencode is used to pass argument as a string - request_parameters = { - StateMachineArn = module.step_function.state_machine_arn - Input = jsonencode({ - "key1" : "value1", - "key2" : "value2" - }) - } - - payload_format_version = "1.0" - timeout_milliseconds = 12000 - } - } - - "$default" = { - integration = { - uri = module.lambda_function.lambda_function_arn - tls_config = { - server_name_to_verify = var.domain_name - } - - response_parameters = [ - { - status_code = 500 - mappings = { - "append:header.header1" = "$context.requestId" - "overwrite:statuscode" = "403" - } - }, - { - status_code = 404 - mappings = { - "append:header.error" = "$stageVariables.environmentId" - } - } - ] - } - } - } - - # Stage - stage_access_log_settings = { - create_log_group = true - log_group_retention_in_days = 7 - format = jsonencode({ - context = { - domainName = "$context.domainName" - integrationErrorMessage = "$context.integrationErrorMessage" - protocol = "$context.protocol" - requestId = "$context.requestId" - requestTime = "$context.requestTime" - responseLength = "$context.responseLength" - routeKey = "$context.routeKey" - stage = "$context.stage" - status = "$context.status" - error = { - message = "$context.error.message" - responseType = "$context.error.responseType" - } - identity = { - sourceIP = "$context.identity.sourceIp" - } - integration = { - error = "$context.integration.error" - integrationStatus = "$context.integration.integrationStatus" - } - } - }) - } - - stage_default_route_settings = { - detailed_metrics_enabled = true - throttling_burst_limit = 100 - throttling_rate_limit = 100 - } - - tags = local.tags -} - -module "api_gateway_disabled" { - source = "../../" - - create = false -} - -################################################################################ -# Supporting Resources -################################################################################ - -resource "aws_apigatewayv2_authorizer" "external" { - api_id = module.api_gateway.api_id - authorizer_type = "JWT" - identity_sources = ["$request.header.Authorization"] - name = local.name - - jwt_configuration { - audience = ["example"] - issuer = "https://${aws_cognito_user_pool.this.endpoint}" - } -} - -resource "aws_cognito_user_pool" "this" { - name = local.name - - tags = local.tags -} - -module "step_function" { - source = "terraform-aws-modules/step-functions/aws" - version = "~> 4.0" - - name = local.name - role_name = "${local.name}-step-function" - trusted_entities = [ - "apigateway.amazonaws.com", - ] - - attach_policies_for_integrations = true - service_integrations = { - stepfunction = { - stepfunction = ["*"] - } - } - - definition = <<-EOT - { - "Comment": "A Hello World example of the Amazon States Language using Pass states", - "StartAt": "Hello", - "States": { - "Hello": { - "Type": "Pass", - "Result": "Hello", - "Next": "World" - }, - "World": { - "Type": "Pass", - "Result": "World", - "End": true - } - } - } - EOT - - tags = local.tags -} - -locals { - package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-function.zip" - downloaded = "downloaded_package_${md5(local.package_url)}.zip" -} - -resource "null_resource" "download_package" { - triggers = { - downloaded = local.downloaded - } - - provisioner "local-exec" { - command = "curl -L -o ${local.downloaded} ${local.package_url}" - } -} - -module "lambda_function" { - source = "terraform-aws-modules/lambda/aws" - version = "~> 7.0" - - function_name = local.name - description = "My awesome lambda function" - handler = "index.lambda_handler" - runtime = "python3.12" - architectures = ["arm64"] - publish = true - - create_package = false - local_existing_package = local.downloaded - - cloudwatch_logs_retention_in_days = 7 - - allowed_triggers = { - AllowExecutionFromAPIGateway = { - service = "apigateway" - source_arn = "${module.api_gateway.api_execution_arn}/*/*" - } - } - - tags = local.tags -} - -################################################################################ -# mTLS Supporting Resources -################################################################################ - -module "s3_bucket" { - source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" - - bucket_prefix = "${local.name}-" - - # NOTE: This is enabled for example usage only, you should not enable this for production workloads - force_destroy = true - - tags = local.tags -} - -resource "aws_s3_object" "this" { - bucket = module.s3_bucket.s3_bucket_id - key = "truststore.pem" - server_side_encryption = "AES256" - content = tls_self_signed_cert.this.cert_pem -} - -resource "tls_private_key" "this" { - algorithm = "RSA" -} - -resource "tls_self_signed_cert" "this" { - is_ca_certificate = true - private_key_pem = tls_private_key.this.private_key_pem - - subject { - common_name = "example.com" - } - - validity_period_hours = 12 - - allowed_uses = [ - "cert_signing", - "server_auth", - ] -} - -resource "local_file" "key" { - content = tls_private_key.this.private_key_pem - filename = "my-key.key" -} - -resource "local_file" "pem" { - content = tls_self_signed_cert.this.cert_pem - filename = "my-cert.pem" -} +provider "aws" { + region = local.region +} + +locals { + name = "ex-${basename(path.cwd)}" + region = "eu-west-1" + + tags = { + Example = local.name + GithubRepo = "terraform-aws-apigateway-v2" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# API Gateway Module +################################################################################ + +module "api_gateway" { + source = "../../" + + # API + body = templatefile("api.yaml", { + example_function_arn = module.lambda_function.lambda_function_arn + }) + + cors_configuration = { + allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] + allow_methods = ["*"] + allow_origins = ["*"] + } + + description = "My awesome HTTP API Gateway" + fail_on_warnings = false + name = local.name + + # Authorizer(s) + authorizers = { + cognito = { + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = "cognito" + jwt_configuration = { + audience = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"] + issuer = "https://${aws_cognito_user_pool.this.endpoint}" + } + } + } + + # Domain Name + domain_name = var.domain_name + create_domain_records = true + create_certificate = true + + mutual_tls_authentication = { + truststore_uri = "s3://${module.s3_bucket.s3_bucket_id}/${aws_s3_object.this.id}" + truststore_version = aws_s3_object.this.version_id + } + + # Routes & Integration(s) + routes = { + "ANY /" = { + detailed_metrics_enabled = false + + integration = { + uri = module.lambda_function.lambda_function_arn + payload_format_version = "2.0" + timeout_milliseconds = 12000 + } + } + + "GET /some-route" = { + authorization_type = "JWT" + authorizer_id = aws_apigatewayv2_authorizer.external.id + throttling_rate_limit = 80 + throttling_burst_limit = 40 + detailed_metrics_enabled = true + + integration = { + uri = module.lambda_function.lambda_function_arn + payload_format_version = "2.0" + } + } + + "GET /some-route-with-authorizer" = { + authorization_type = "JWT" + authorizer_key = "cognito" + + integration = { + uri = module.lambda_function.lambda_function_arn + payload_format_version = "2.0" + } + } + + "GET /some-route-with-authorizer-and-scope" = { + authorization_type = "JWT" + authorizer_key = "cognito" + authorization_scopes = ["user.id", "user.email"] + + integration = { + uri = module.lambda_function.lambda_function_arn + payload_format_version = "2.0" + } + } + + "POST /start-step-function" = { + integration = { + type = "AWS_PROXY" + subtype = "StepFunctions-StartExecution" + credentials_arn = module.step_function.role_arn + + # Note: jsonencode is used to pass argument as a string + request_parameters = { + StateMachineArn = module.step_function.state_machine_arn + Input = jsonencode({ + "key1" : "value1", + "key2" : "value2" + }) + } + + payload_format_version = "1.0" + timeout_milliseconds = 12000 + } + } + + "$default" = { + integration = { + uri = module.lambda_function.lambda_function_arn + tls_config = { + server_name_to_verify = var.domain_name + } + + response_parameters = [ + { + status_code = 500 + mappings = { + "append:header.header1" = "$context.requestId" + "overwrite:statuscode" = "403" + } + }, + { + status_code = 404 + mappings = { + "append:header.error" = "$stageVariables.environmentId" + } + } + ] + } + } + } + + # Stage + stage_access_log_settings = { + create_log_group = true + log_group_retention_in_days = 7 + format = jsonencode({ + context = { + domainName = "$context.domainName" + integrationErrorMessage = "$context.integrationErrorMessage" + protocol = "$context.protocol" + requestId = "$context.requestId" + requestTime = "$context.requestTime" + responseLength = "$context.responseLength" + routeKey = "$context.routeKey" + stage = "$context.stage" + status = "$context.status" + error = { + message = "$context.error.message" + responseType = "$context.error.responseType" + } + identity = { + sourceIP = "$context.identity.sourceIp" + } + integration = { + error = "$context.integration.error" + integrationStatus = "$context.integration.integrationStatus" + } + } + }) + } + + stage_default_route_settings = { + detailed_metrics_enabled = true + throttling_burst_limit = 100 + throttling_rate_limit = 100 + } + + tags = local.tags +} + +module "api_gateway_disabled" { + source = "../../" + + create = false +} + +################################################################################ +# Supporting Resources +################################################################################ + +resource "aws_apigatewayv2_authorizer" "external" { + api_id = module.api_gateway.api_id + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = local.name + + jwt_configuration { + audience = ["example"] + issuer = "https://${aws_cognito_user_pool.this.endpoint}" + } +} + +resource "aws_cognito_user_pool" "this" { + name = local.name + + tags = local.tags +} + +module "step_function" { + source = "terraform-aws-modules/step-functions/aws" + version = "~> 4.0" + + name = local.name + role_name = "${local.name}-step-function" + trusted_entities = [ + "apigateway.amazonaws.com", + ] + + attach_policies_for_integrations = true + service_integrations = { + stepfunction = { + stepfunction = ["*"] + } + } + + definition = <<-EOT + { + "Comment": "A Hello World example of the Amazon States Language using Pass states", + "StartAt": "Hello", + "States": { + "Hello": { + "Type": "Pass", + "Result": "Hello", + "Next": "World" + }, + "World": { + "Type": "Pass", + "Result": "World", + "End": true + } + } + } + EOT + + tags = local.tags +} + +locals { + package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-function.zip" + downloaded = "downloaded_package_${md5(local.package_url)}.zip" +} + +resource "null_resource" "download_package" { + triggers = { + downloaded = local.downloaded + } + + provisioner "local-exec" { + command = "curl -L -o ${local.downloaded} ${local.package_url}" + } +} + +module "lambda_function" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 7.0" + + function_name = local.name + description = "My awesome lambda function" + handler = "index.lambda_handler" + runtime = "python3.12" + architectures = ["arm64"] + publish = true + + create_package = false + local_existing_package = local.downloaded + + cloudwatch_logs_retention_in_days = 7 + + allowed_triggers = { + AllowExecutionFromAPIGateway = { + service = "apigateway" + source_arn = "${module.api_gateway.api_execution_arn}/*/*" + } + } + + tags = local.tags +} + +################################################################################ +# mTLS Supporting Resources +################################################################################ + +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "~> 3.0" + + bucket_prefix = "${local.name}-" + + # NOTE: This is enabled for example usage only, you should not enable this for production workloads + force_destroy = true + + tags = local.tags +} + +resource "aws_s3_object" "this" { + bucket = module.s3_bucket.s3_bucket_id + key = "truststore.pem" + server_side_encryption = "AES256" + content = tls_self_signed_cert.this.cert_pem +} + +resource "tls_private_key" "this" { + algorithm = "RSA" +} + +resource "tls_self_signed_cert" "this" { + is_ca_certificate = true + private_key_pem = tls_private_key.this.private_key_pem + + subject { + common_name = "example.com" + } + + validity_period_hours = 12 + + allowed_uses = [ + "cert_signing", + "server_auth", + ] +} + +resource "local_file" "key" { + content = tls_private_key.this.private_key_pem + filename = "my-key.key" +} + +resource "local_file" "pem" { + content = tls_self_signed_cert.this.cert_pem + filename = "my-cert.pem" +} diff --git a/examples/complete-http/outputs.tf b/examples/complete-http/outputs.tf index b3b1846..4393caa 100644 --- a/examples/complete-http/outputs.tf +++ b/examples/complete-http/outputs.tf @@ -1,150 +1,150 @@ -output "test_curl_command" { - description = "Curl command to test API endpoint using mTLS" - value = "curl --key ./my-key.key --cert ./my-cert.pem https://${var.domain_name} | jq" -} - -################################################################################ -# API Gateway -################################################################################ - -output "api_id" { - description = "The API identifier" - value = module.api_gateway.api_id -} - -output "api_endpoint" { - description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" - value = module.api_gateway.api_endpoint -} - -output "api_arn" { - description = "The ARN of the API" - value = module.api_gateway.api_arn -} - -output "api_execution_arn" { - description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" - value = module.api_gateway.api_execution_arn -} - -################################################################################ -# Authorizer(s) -################################################################################ - -output "authorizers" { - description = "Map of API Gateway Authorizer(s) created and their attributes" - value = module.api_gateway.authorizers -} - -################################################################################ -# Domain Name -################################################################################ - -output "domain_name_id" { - description = "The domain name identifier" - value = module.api_gateway.domain_name_id -} - -output "domain_name_arn" { - description = "The ARN of the domain name" - value = module.api_gateway.domain_name_arn -} - -output "domain_name_api_mapping_selection_expression" { - description = "The API mapping selection expression for the domain name" - value = module.api_gateway.domain_name_api_mapping_selection_expression -} - -output "domain_name_configuration" { - description = "The domain name configuration" - value = module.api_gateway.domain_name_configuration -} - -output "domain_name_target_domain_name" { - description = "The target domain name" - value = module.api_gateway.domain_name_target_domain_name -} - -output "domain_name_hosted_zone_id" { - description = "The Amazon Route 53 Hosted Zone ID of the endpoint" - value = module.api_gateway.domain_name_hosted_zone_id -} - -################################################################################ -# Domain - Certificate -################################################################################ - -output "acm_certificate_arn" { - description = "The ARN of the certificate" - value = module.api_gateway.acm_certificate_arn -} - -################################################################################ -# Integration(s) -################################################################################ - -output "integrations" { - description = "Map of the integrations created and their attributes" - value = module.api_gateway.integrations -} - -################################################################################ -# Route(s) -################################################################################ - -output "routes" { - description = "Map of the routes created and their attributes" - value = module.api_gateway.routes -} - -################################################################################ -# Stage -################################################################################ - -output "stage_id" { - description = "The stage identifier" - value = module.api_gateway.stage_id -} - -output "stage_domain_name" { - description = "Domain name of the stage (useful for CloudFront distribution)" - value = module.api_gateway.stage_domain_name -} - -output "stage_arn" { - description = "The stage ARN" - value = module.api_gateway.stage_arn -} - -output "stage_execution_arn" { - description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" - value = module.api_gateway.stage_execution_arn -} - -output "stage_invoke_url" { - description = "The URL to invoke the API pointing to the stage" - value = module.api_gateway.stage_invoke_url -} - -################################################################################ -# Stage Access Logs - Log Group -################################################################################ - -output "stage_access_logs_cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name -} - -output "stage_access_logs_cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn -} - -################################################################################ -# VPC Link -################################################################################ - -output "vpc_links" { - description = "Map of VPC links created and their attributes" - value = module.api_gateway.vpc_links -} +output "test_curl_command" { + description = "Curl command to test API endpoint using mTLS" + value = "curl --key ./my-key.key --cert ./my-cert.pem https://${var.domain_name} | jq" +} + +################################################################################ +# API Gateway +################################################################################ + +output "api_id" { + description = "The API identifier" + value = module.api_gateway.api_id +} + +output "api_endpoint" { + description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" + value = module.api_gateway.api_endpoint +} + +output "api_arn" { + description = "The ARN of the API" + value = module.api_gateway.api_arn +} + +output "api_execution_arn" { + description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" + value = module.api_gateway.api_execution_arn +} + +################################################################################ +# Authorizer(s) +################################################################################ + +output "authorizers" { + description = "Map of API Gateway Authorizer(s) created and their attributes" + value = module.api_gateway.authorizers +} + +################################################################################ +# Domain Name +################################################################################ + +output "domain_name_id" { + description = "The domain name identifier" + value = module.api_gateway.domain_name_id +} + +output "domain_name_arn" { + description = "The ARN of the domain name" + value = module.api_gateway.domain_name_arn +} + +output "domain_name_api_mapping_selection_expression" { + description = "The API mapping selection expression for the domain name" + value = module.api_gateway.domain_name_api_mapping_selection_expression +} + +output "domain_name_configuration" { + description = "The domain name configuration" + value = module.api_gateway.domain_name_configuration +} + +output "domain_name_target_domain_name" { + description = "The target domain name" + value = module.api_gateway.domain_name_target_domain_name +} + +output "domain_name_hosted_zone_id" { + description = "The Amazon Route 53 Hosted Zone ID of the endpoint" + value = module.api_gateway.domain_name_hosted_zone_id +} + +################################################################################ +# Domain - Certificate +################################################################################ + +output "acm_certificate_arn" { + description = "The ARN of the certificate" + value = module.api_gateway.acm_certificate_arn +} + +################################################################################ +# Integration(s) +################################################################################ + +output "integrations" { + description = "Map of the integrations created and their attributes" + value = module.api_gateway.integrations +} + +################################################################################ +# Route(s) +################################################################################ + +output "routes" { + description = "Map of the routes created and their attributes" + value = module.api_gateway.routes +} + +################################################################################ +# Stage +################################################################################ + +output "stage_id" { + description = "The stage identifier" + value = module.api_gateway.stage_id +} + +output "stage_domain_name" { + description = "Domain name of the stage (useful for CloudFront distribution)" + value = module.api_gateway.stage_domain_name +} + +output "stage_arn" { + description = "The stage ARN" + value = module.api_gateway.stage_arn +} + +output "stage_execution_arn" { + description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" + value = module.api_gateway.stage_execution_arn +} + +output "stage_invoke_url" { + description = "The URL to invoke the API pointing to the stage" + value = module.api_gateway.stage_invoke_url +} + +################################################################################ +# Stage Access Logs - Log Group +################################################################################ + +output "stage_access_logs_cloudwatch_log_group_name" { + description = "Name of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name +} + +output "stage_access_logs_cloudwatch_log_group_arn" { + description = "Arn of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn +} + +################################################################################ +# VPC Link +################################################################################ + +output "vpc_links" { + description = "Map of VPC links created and their attributes" + value = module.api_gateway.vpc_links +} diff --git a/examples/complete-http/variables.tf b/examples/complete-http/variables.tf index 06f03dd..fa836c2 100644 --- a/examples/complete-http/variables.tf +++ b/examples/complete-http/variables.tf @@ -1,5 +1,5 @@ -variable "domain_name" { - description = "Custom domain name to use on API Gateway endpoint" - type = string - default = "terraform-aws-modules.modules.tf" -} +variable "domain_name" { + description = "Custom domain name to use on API Gateway endpoint" + type = string + default = "terraform-aws-modules.modules.tf" +} diff --git a/examples/complete-http/versions.tf b/examples/complete-http/versions.tf index 61e4e49..9884fe9 100644 --- a/examples/complete-http/versions.tf +++ b/examples/complete-http/versions.tf @@ -1,22 +1,22 @@ -terraform { - required_version = ">= 1.3" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.96" - } - local = { - source = "hashicorp/local" - version = ">= 2.5" - } - null = { - source = "hashicorp/null" - version = ">= 2.0" - } - tls = { - source = "hashicorp/tls" - version = ">= 3.1" - } - } -} +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.96" + } + local = { + source = "hashicorp/local" + version = ">= 2.5" + } + null = { + source = "hashicorp/null" + version = ">= 2.0" + } + tls = { + source = "hashicorp/tls" + version = ">= 3.1" + } + } +} diff --git a/examples/vpc-link-http/README.md b/examples/vpc-link-http/README.md index 795d199..544e3e2 100644 --- a/examples/vpc-link-http/README.md +++ b/examples/vpc-link-http/README.md @@ -1,19 +1,19 @@ -# AWS API Gateway w/ VPC Links example - -Configuration in this directory creates a private AWS API Gateway with VPC link and integrates it with a VPC bound resources (Lambda function and ALB). - -## Usage - -To run this example you need to execute: - -```bash -$ terraform init -$ terraform plan -$ terraform apply -``` - -Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. - +# AWS API Gateway w/ VPC Links example + +Configuration in this directory creates a private AWS API Gateway with VPC link and integrates it with a VPC bound resources (Lambda function and ALB). + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. + ## Requirements @@ -78,6 +78,6 @@ No inputs. | [stage\_id](#output\_stage\_id) | The stage identifier | | [stage\_invoke\_url](#output\_stage\_invoke\_url) | The URL to invoke the API pointing to the stage | | [vpc\_links](#output\_vpc\_links) | Map of VPC links created and their attributes | - - -Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). + + +Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). diff --git a/examples/vpc-link-http/main.tf b/examples/vpc-link-http/main.tf index 77f238b..4ab4c1a 100644 --- a/examples/vpc-link-http/main.tf +++ b/examples/vpc-link-http/main.tf @@ -1,226 +1,226 @@ -provider "aws" { - region = local.region -} - -data "aws_availability_zones" "available" {} - -locals { - name = "ex-${basename(path.cwd)}" - region = "eu-west-1" - - vpc_cidr = "10.0.0.0/16" - azs = slice(data.aws_availability_zones.available.names, 0, 3) - - tags = { - Example = local.name - GithubRepo = "terraform-aws-apigateway-v2" - GithubOrg = "terraform-aws-modules" - } -} - -################################################################################ -# API Gateway Module -################################################################################ - -module "api_gateway" { - source = "../../" - - # API - cors_configuration = { - allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] - allow_methods = ["*"] - allow_origins = ["*"] - } - - description = "HTTP API Gateway with VPC links" - name = local.name - - # Custom Domain - create_domain_name = false - - # Routes & Integration(s) - routes = { - "ANY /" = { - integration = { - uri = module.lambda_function.lambda_function_arn - payload_format_version = "2.0" - timeout_milliseconds = 12000 - } - } - - "GET /alb-internal-route" = { - integration = { - connection_type = "VPC_LINK" - uri = module.alb.listeners["default"].arn - type = "HTTP_PROXY" - method = "ANY" - vpc_link_key = "my-vpc" - } - } - - "$default" = { - integration = { - uri = module.lambda_function.lambda_function_arn - } - } - } - - # VPC Link - vpc_links = { - my-vpc = { - name = local.name - security_group_ids = [module.api_gateway_security_group.security_group_id] - subnet_ids = module.vpc.public_subnets - } - } - - tags = local.tags -} - -################################################################################ -# Supporting Resources -################################################################################ - -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" - - name = local.name - cidr = local.vpc_cidr - - azs = local.azs - private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] - public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] - - enable_nat_gateway = true - single_nat_gateway = true - - tags = local.tags -} - -module "api_gateway_security_group" { - source = "terraform-aws-modules/security-group/aws" - version = "~> 5.0" - - name = local.name - description = "API Gateway group for example usage" - vpc_id = module.vpc.vpc_id - - ingress_cidr_blocks = ["0.0.0.0/0"] - ingress_rules = ["http-80-tcp"] - - egress_rules = ["all-all"] - - tags = local.tags -} - -module "alb" { - source = "terraform-aws-modules/alb/aws" - version = "~> 9.0" - - name = local.name - - vpc_id = module.vpc.vpc_id - subnets = module.vpc.public_subnets - - # Disable for example - enable_deletion_protection = false - - security_group_ingress_rules = { - all_http = { - from_port = 80 - to_port = 80 - ip_protocol = "tcp" - description = "HTTP web traffic" - cidr_ipv4 = "0.0.0.0/0" - } - all_https = { - from_port = 443 - to_port = 443 - ip_protocol = "tcp" - description = "HTTPS web traffic" - cidr_ipv4 = "0.0.0.0/0" - } - } - - listeners = { - default = { - port = 80 - protocol = "HTTP" - fixed_response = { - content_type = "text/plain" - message_body = "Hello, World!" - status_code = "200" - } - } - } - - tags = local.tags -} - - -locals { - package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-function.zip" - downloaded = "downloaded_package_${md5(local.package_url)}.zip" -} - -resource "null_resource" "download_package" { - triggers = { - downloaded = local.downloaded - } - - provisioner "local-exec" { - command = "curl -L -o ${local.downloaded} ${local.package_url}" - } -} - -module "lambda_function" { - source = "terraform-aws-modules/lambda/aws" - version = "~> 7.0" - - function_name = local.name - description = "My awesome lambda function" - handler = "index.lambda_handler" - runtime = "python3.12" - architectures = ["arm64"] - publish = true - - create_package = false - local_existing_package = local.downloaded - - cloudwatch_logs_retention_in_days = 7 - - attach_network_policy = true - vpc_subnet_ids = module.vpc.private_subnets - vpc_security_group_ids = [module.lambda_security_group.security_group_id] - - allowed_triggers = { - AllowExecutionFromAPIGateway = { - service = "apigateway" - source_arn = "${module.api_gateway.api_execution_arn}/*/*" - } - } - - tags = local.tags -} - -module "lambda_security_group" { - source = "terraform-aws-modules/security-group/aws" - version = "~> 5.0" - - name = "${local.name}-lambda" - description = "Lambda security group for example usage" - vpc_id = module.vpc.vpc_id - - computed_ingress_with_source_security_group_id = [ - { - rule = "http-80-tcp" - source_security_group_id = module.api_gateway_security_group.security_group_id - } - ] - number_of_computed_ingress_with_source_security_group_id = 1 - - egress_rules = ["all-all"] - - tags = local.tags -} +provider "aws" { + region = local.region +} + +data "aws_availability_zones" "available" {} + +locals { + name = "ex-${basename(path.cwd)}" + region = "eu-west-1" + + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + + tags = { + Example = local.name + GithubRepo = "terraform-aws-apigateway-v2" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# API Gateway Module +################################################################################ + +module "api_gateway" { + source = "../../" + + # API + cors_configuration = { + allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"] + allow_methods = ["*"] + allow_origins = ["*"] + } + + description = "HTTP API Gateway with VPC links" + name = local.name + + # Custom Domain + create_domain_name = false + + # Routes & Integration(s) + routes = { + "ANY /" = { + integration = { + uri = module.lambda_function.lambda_function_arn + payload_format_version = "2.0" + timeout_milliseconds = 12000 + } + } + + "GET /alb-internal-route" = { + integration = { + connection_type = "VPC_LINK" + uri = module.alb.listeners["default"].arn + type = "HTTP_PROXY" + method = "ANY" + vpc_link_key = "my-vpc" + } + } + + "$default" = { + integration = { + uri = module.lambda_function.lambda_function_arn + } + } + } + + # VPC Link + vpc_links = { + my-vpc = { + name = local.name + security_group_ids = [module.api_gateway_security_group.security_group_id] + subnet_ids = module.vpc.public_subnets + } + } + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = local.name + cidr = local.vpc_cidr + + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] + + enable_nat_gateway = true + single_nat_gateway = true + + tags = local.tags +} + +module "api_gateway_security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 5.0" + + name = local.name + description = "API Gateway group for example usage" + vpc_id = module.vpc.vpc_id + + ingress_cidr_blocks = ["0.0.0.0/0"] + ingress_rules = ["http-80-tcp"] + + egress_rules = ["all-all"] + + tags = local.tags +} + +module "alb" { + source = "terraform-aws-modules/alb/aws" + version = "~> 9.0" + + name = local.name + + vpc_id = module.vpc.vpc_id + subnets = module.vpc.public_subnets + + # Disable for example + enable_deletion_protection = false + + security_group_ingress_rules = { + all_http = { + from_port = 80 + to_port = 80 + ip_protocol = "tcp" + description = "HTTP web traffic" + cidr_ipv4 = "0.0.0.0/0" + } + all_https = { + from_port = 443 + to_port = 443 + ip_protocol = "tcp" + description = "HTTPS web traffic" + cidr_ipv4 = "0.0.0.0/0" + } + } + + listeners = { + default = { + port = 80 + protocol = "HTTP" + fixed_response = { + content_type = "text/plain" + message_body = "Hello, World!" + status_code = "200" + } + } + } + + tags = local.tags +} + + +locals { + package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-function.zip" + downloaded = "downloaded_package_${md5(local.package_url)}.zip" +} + +resource "null_resource" "download_package" { + triggers = { + downloaded = local.downloaded + } + + provisioner "local-exec" { + command = "curl -L -o ${local.downloaded} ${local.package_url}" + } +} + +module "lambda_function" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 7.0" + + function_name = local.name + description = "My awesome lambda function" + handler = "index.lambda_handler" + runtime = "python3.12" + architectures = ["arm64"] + publish = true + + create_package = false + local_existing_package = local.downloaded + + cloudwatch_logs_retention_in_days = 7 + + attach_network_policy = true + vpc_subnet_ids = module.vpc.private_subnets + vpc_security_group_ids = [module.lambda_security_group.security_group_id] + + allowed_triggers = { + AllowExecutionFromAPIGateway = { + service = "apigateway" + source_arn = "${module.api_gateway.api_execution_arn}/*/*" + } + } + + tags = local.tags +} + +module "lambda_security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 5.0" + + name = "${local.name}-lambda" + description = "Lambda security group for example usage" + vpc_id = module.vpc.vpc_id + + computed_ingress_with_source_security_group_id = [ + { + rule = "http-80-tcp" + source_security_group_id = module.api_gateway_security_group.security_group_id + } + ] + number_of_computed_ingress_with_source_security_group_id = 1 + + egress_rules = ["all-all"] + + tags = local.tags +} diff --git a/examples/vpc-link-http/outputs.tf b/examples/vpc-link-http/outputs.tf index 29e5677..00299b2 100644 --- a/examples/vpc-link-http/outputs.tf +++ b/examples/vpc-link-http/outputs.tf @@ -1,145 +1,145 @@ -################################################################################ -# API Gateway -################################################################################ - -output "api_id" { - description = "The API identifier" - value = module.api_gateway.api_id -} - -output "api_endpoint" { - description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" - value = module.api_gateway.api_endpoint -} - -output "api_arn" { - description = "The ARN of the API" - value = module.api_gateway.api_arn -} - -output "api_execution_arn" { - description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" - value = module.api_gateway.api_execution_arn -} - -################################################################################ -# Authorizer(s) -################################################################################ - -output "authorizers" { - description = "Map of API Gateway Authorizer(s) created and their attributes" - value = module.api_gateway.authorizers -} - -################################################################################ -# Domain Name -################################################################################ - -output "domain_name_id" { - description = "The domain name identifier" - value = module.api_gateway.domain_name_id -} - -output "stage_domain_name" { - description = "Domain name of the stage (useful for CloudFront distribution)" - value = module.api_gateway.stage_domain_name -} - -output "domain_name_arn" { - description = "The ARN of the domain name" - value = module.api_gateway.domain_name_arn -} - -output "domain_name_api_mapping_selection_expression" { - description = "The API mapping selection expression for the domain name" - value = module.api_gateway.domain_name_api_mapping_selection_expression -} - -output "domain_name_configuration" { - description = "The domain name configuration" - value = module.api_gateway.domain_name_configuration -} - -output "domain_name_target_domain_name" { - description = "The target domain name" - value = module.api_gateway.domain_name_target_domain_name -} - -output "domain_name_hosted_zone_id" { - description = "The Amazon Route 53 Hosted Zone ID of the endpoint" - value = module.api_gateway.domain_name_hosted_zone_id -} - -################################################################################ -# Domain - Certificate -################################################################################ - -output "acm_certificate_arn" { - description = "The ARN of the certificate" - value = module.api_gateway.acm_certificate_arn -} - -################################################################################ -# Integration(s) -################################################################################ - -output "integrations" { - description = "Map of the integrations created and their attributes" - value = module.api_gateway.integrations -} - -################################################################################ -# Route(s) -################################################################################ - -output "routes" { - description = "Map of the routes created and their attributes" - value = module.api_gateway.routes -} - -################################################################################ -# Stage -################################################################################ - -output "stage_id" { - description = "The stage identifier" - value = module.api_gateway.stage_id -} - -output "stage_arn" { - description = "The stage ARN" - value = module.api_gateway.stage_arn -} - -output "stage_execution_arn" { - description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" - value = module.api_gateway.stage_execution_arn -} - -output "stage_invoke_url" { - description = "The URL to invoke the API pointing to the stage" - value = module.api_gateway.stage_invoke_url -} - -################################################################################ -# Stage Access Logs - Log Group -################################################################################ - -output "stage_access_logs_cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name -} - -output "stage_access_logs_cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn -} - -################################################################################ -# VPC Link -################################################################################ - -output "vpc_links" { - description = "Map of VPC links created and their attributes" - value = module.api_gateway.vpc_links -} +################################################################################ +# API Gateway +################################################################################ + +output "api_id" { + description = "The API identifier" + value = module.api_gateway.api_id +} + +output "api_endpoint" { + description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" + value = module.api_gateway.api_endpoint +} + +output "api_arn" { + description = "The ARN of the API" + value = module.api_gateway.api_arn +} + +output "api_execution_arn" { + description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" + value = module.api_gateway.api_execution_arn +} + +################################################################################ +# Authorizer(s) +################################################################################ + +output "authorizers" { + description = "Map of API Gateway Authorizer(s) created and their attributes" + value = module.api_gateway.authorizers +} + +################################################################################ +# Domain Name +################################################################################ + +output "domain_name_id" { + description = "The domain name identifier" + value = module.api_gateway.domain_name_id +} + +output "stage_domain_name" { + description = "Domain name of the stage (useful for CloudFront distribution)" + value = module.api_gateway.stage_domain_name +} + +output "domain_name_arn" { + description = "The ARN of the domain name" + value = module.api_gateway.domain_name_arn +} + +output "domain_name_api_mapping_selection_expression" { + description = "The API mapping selection expression for the domain name" + value = module.api_gateway.domain_name_api_mapping_selection_expression +} + +output "domain_name_configuration" { + description = "The domain name configuration" + value = module.api_gateway.domain_name_configuration +} + +output "domain_name_target_domain_name" { + description = "The target domain name" + value = module.api_gateway.domain_name_target_domain_name +} + +output "domain_name_hosted_zone_id" { + description = "The Amazon Route 53 Hosted Zone ID of the endpoint" + value = module.api_gateway.domain_name_hosted_zone_id +} + +################################################################################ +# Domain - Certificate +################################################################################ + +output "acm_certificate_arn" { + description = "The ARN of the certificate" + value = module.api_gateway.acm_certificate_arn +} + +################################################################################ +# Integration(s) +################################################################################ + +output "integrations" { + description = "Map of the integrations created and their attributes" + value = module.api_gateway.integrations +} + +################################################################################ +# Route(s) +################################################################################ + +output "routes" { + description = "Map of the routes created and their attributes" + value = module.api_gateway.routes +} + +################################################################################ +# Stage +################################################################################ + +output "stage_id" { + description = "The stage identifier" + value = module.api_gateway.stage_id +} + +output "stage_arn" { + description = "The stage ARN" + value = module.api_gateway.stage_arn +} + +output "stage_execution_arn" { + description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" + value = module.api_gateway.stage_execution_arn +} + +output "stage_invoke_url" { + description = "The URL to invoke the API pointing to the stage" + value = module.api_gateway.stage_invoke_url +} + +################################################################################ +# Stage Access Logs - Log Group +################################################################################ + +output "stage_access_logs_cloudwatch_log_group_name" { + description = "Name of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name +} + +output "stage_access_logs_cloudwatch_log_group_arn" { + description = "Arn of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn +} + +################################################################################ +# VPC Link +################################################################################ + +output "vpc_links" { + description = "Map of VPC links created and their attributes" + value = module.api_gateway.vpc_links +} diff --git a/examples/vpc-link-http/versions.tf b/examples/vpc-link-http/versions.tf index 7082bff..979e07a 100644 --- a/examples/vpc-link-http/versions.tf +++ b/examples/vpc-link-http/versions.tf @@ -1,14 +1,14 @@ -terraform { - required_version = ">= 1.3" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.96" - } - null = { - source = "hashicorp/null" - version = ">= 2.0" - } - } -} +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.96" + } + null = { + source = "hashicorp/null" + version = ">= 2.0" + } + } +} diff --git a/examples/websocket/README.md b/examples/websocket/README.md index a549ee6..d30197d 100644 --- a/examples/websocket/README.md +++ b/examples/websocket/README.md @@ -1,50 +1,50 @@ -# AWS Websocket API example - -Configuration in this directory creates an AWS Websocket API. -This example is based off of https://github.com/aws-samples/simple-websockets-chat-app - -## Usage - -To run this example you need to execute: - -```bash -$ terraform init -$ terraform plan -$ terraform apply -``` - -Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. - -## Testing the chat API - -To test the WebSocket API, you can use [wscat](https://github.com/websockets/wscat), an open-source command line tool. - -1. [Install NPM](https://www.npmjs.com/get-npm). -2. Install wscat: - -```bash -$ npm install -g wscat -``` - -3. On the console, connect to your published API endpoint by executing the following command: - -> [!NOTE] -> It will take a few seconds on a new API for the endpoint to respond. -> If you see a 403 error, give it a few seconds and try again - only one new APIs that were just created. - -```bash -$ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE} -``` - -4. To test the sendMessage function, send a JSON message like the following example. The Lambda function sends it back using the callback URL: - -```bash -$ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE} -connected (press CTRL+C to quit) -> {"action":"sendmessage", "data":"hello world"} -< hello world -``` - +# AWS Websocket API example + +Configuration in this directory creates an AWS Websocket API. +This example is based off of https://github.com/aws-samples/simple-websockets-chat-app + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. + +## Testing the chat API + +To test the WebSocket API, you can use [wscat](https://github.com/websockets/wscat), an open-source command line tool. + +1. [Install NPM](https://www.npmjs.com/get-npm). +2. Install wscat: + +```bash +$ npm install -g wscat +``` + +3. On the console, connect to your published API endpoint by executing the following command: + +> [!NOTE] +> It will take a few seconds on a new API for the endpoint to respond. +> If you see a 403 error, give it a few seconds and try again - only one new APIs that were just created. + +```bash +$ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE} +``` + +4. To test the sendMessage function, send a JSON message like the following example. The Lambda function sends it back using the callback URL: + +```bash +$ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE} +connected (press CTRL+C to quit) +> {"action":"sendmessage", "data":"hello world"} +< hello world +``` + ## Requirements @@ -101,6 +101,6 @@ No inputs. | [stage\_id](#output\_stage\_id) | The stage identifier | | [stage\_invoke\_url](#output\_stage\_invoke\_url) | The URL to invoke the API pointing to the stage | | [vpc\_links](#output\_vpc\_links) | Map of VPC links created and their attributes | - - -Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). + + +Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-apigateway-v2/blob/master/LICENSE). diff --git a/examples/websocket/function/onConnect.js b/examples/websocket/function/onConnect.js index b7f6045..f1e07be 100644 --- a/examples/websocket/function/onConnect.js +++ b/examples/websocket/function/onConnect.js @@ -1,27 +1,27 @@ -const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); -const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb"); - -// DynamoDB clients -const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); -const docClient = DynamoDBDocumentClient.from(ddbClient); - -exports.handler = async (event) => { - const command = new PutCommand({ - TableName: process.env.TABLE_NAME, - Item: { - connectionId: event.requestContext.connectionId, - }, - }); - - try { - const response = await docClient.send(command); - console.log(JSON.stringify(response)); - } catch (err) { - return { - statusCode: 500, - body: "Failed to connect: " + JSON.stringify(err), - }; - } - - return { statusCode: 200, body: "Connected." }; -}; +const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); +const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb"); + +// DynamoDB clients +const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); +const docClient = DynamoDBDocumentClient.from(ddbClient); + +exports.handler = async (event) => { + const command = new PutCommand({ + TableName: process.env.TABLE_NAME, + Item: { + connectionId: event.requestContext.connectionId, + }, + }); + + try { + const response = await docClient.send(command); + console.log(JSON.stringify(response)); + } catch (err) { + return { + statusCode: 500, + body: "Failed to connect: " + JSON.stringify(err), + }; + } + + return { statusCode: 200, body: "Connected." }; +}; diff --git a/examples/websocket/function/onDisconnect.js b/examples/websocket/function/onDisconnect.js index 52a388d..ed1a461 100644 --- a/examples/websocket/function/onDisconnect.js +++ b/examples/websocket/function/onDisconnect.js @@ -1,33 +1,33 @@ -// https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-route-keys-connect-disconnect.html -// The $disconnect route is executed after the connection is closed. -// The connection can be closed by the server or by the client. As the connection is already closed when it is executed, -// $disconnect is a best-effort event. -// API Gateway will try its best to deliver the $disconnect event to your integration, but it cannot guarantee delivery. - -const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); -const { DynamoDBDocumentClient, DeleteCommand } = require("@aws-sdk/lib-dynamodb"); - -// DynamoDB clients -const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); -const docClient = DynamoDBDocumentClient.from(ddbClient); - -exports.handler = async (event) => { - const command = new DeleteCommand({ - TableName: process.env.TABLE_NAME, - Key: { - connectionId: event.requestContext.connectionId, - }, - }); - - try { - const response = await docClient.send(command); - console.log(JSON.stringify(response)); - } catch (err) { - return { - statusCode: 500, - body: "Failed to disconnect: " + JSON.stringify(err), - }; - } - - return { statusCode: 200, body: "Disconnected." }; -}; +// https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-route-keys-connect-disconnect.html +// The $disconnect route is executed after the connection is closed. +// The connection can be closed by the server or by the client. As the connection is already closed when it is executed, +// $disconnect is a best-effort event. +// API Gateway will try its best to deliver the $disconnect event to your integration, but it cannot guarantee delivery. + +const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); +const { DynamoDBDocumentClient, DeleteCommand } = require("@aws-sdk/lib-dynamodb"); + +// DynamoDB clients +const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); +const docClient = DynamoDBDocumentClient.from(ddbClient); + +exports.handler = async (event) => { + const command = new DeleteCommand({ + TableName: process.env.TABLE_NAME, + Key: { + connectionId: event.requestContext.connectionId, + }, + }); + + try { + const response = await docClient.send(command); + console.log(JSON.stringify(response)); + } catch (err) { + return { + statusCode: 500, + body: "Failed to disconnect: " + JSON.stringify(err), + }; + } + + return { statusCode: 200, body: "Disconnected." }; +}; diff --git a/examples/websocket/function/sendMessage.js b/examples/websocket/function/sendMessage.js index 2f6fcee..8f8fe3e 100644 --- a/examples/websocket/function/sendMessage.js +++ b/examples/websocket/function/sendMessage.js @@ -1,54 +1,54 @@ -const { ApiGatewayManagementApiClient, PostToConnectionCommand } = require("@aws-sdk/client-apigatewaymanagementapi"); -const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); -const { DynamoDBDocumentClient, DeleteCommand, ScanCommand } = require("@aws-sdk/lib-dynamodb"); - -// DynamoDB clients -const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); -const docClient = DynamoDBDocumentClient.from(ddbClient); - -exports.handler = async (event) => { - const scanCommand = new ScanCommand({ - ProjectionExpression: "connectionId", - TableName: process.env.TABLE_NAME, - }); - - const scanData = await docClient.send(scanCommand); - - const domain = event.requestContext.domainName; - const stage = event.requestContext.stage; - const postData = JSON.parse(event.body).data; - - // API Gateway Management API client - const apiClient = new ApiGatewayManagementApiClient({ - region: process.env.AWS_REGION, - endpoint: `https://${domain}/${stage}`, - }); - - scanData.Items.map(async ({ connectionId }) => { - try { - const apiCommand = new PostToConnectionCommand({ - ConnectionId: connectionId, - Data: postData, - }) - const response = await apiClient.send(apiCommand); - console.log(JSON.stringify(response)); - - } catch (e) { - if (e.name === 'GoneException') { return; } - if (e.statusCode === 410) { - console.log(`Found stale connection, deleting ${connectionId}`); - const command = new DeleteCommand({ - TableName: process.env.TABLE_NAME, - Key: { connectionId }, - }); - - const response = await docClient.send(command); - console.log(JSON.stringify(response)); - } else { - throw e; - } - } - }); - - return { statusCode: 200, body: "Data sent." }; -}; +const { ApiGatewayManagementApiClient, PostToConnectionCommand } = require("@aws-sdk/client-apigatewaymanagementapi"); +const { DynamoDBClient, } = require("@aws-sdk/client-dynamodb"); +const { DynamoDBDocumentClient, DeleteCommand, ScanCommand } = require("@aws-sdk/lib-dynamodb"); + +// DynamoDB clients +const ddbClient = new DynamoDBClient({ region: process.env.AWS_REGION }); +const docClient = DynamoDBDocumentClient.from(ddbClient); + +exports.handler = async (event) => { + const scanCommand = new ScanCommand({ + ProjectionExpression: "connectionId", + TableName: process.env.TABLE_NAME, + }); + + const scanData = await docClient.send(scanCommand); + + const domain = event.requestContext.domainName; + const stage = event.requestContext.stage; + const postData = JSON.parse(event.body).data; + + // API Gateway Management API client + const apiClient = new ApiGatewayManagementApiClient({ + region: process.env.AWS_REGION, + endpoint: `https://${domain}/${stage}`, + }); + + scanData.Items.map(async ({ connectionId }) => { + try { + const apiCommand = new PostToConnectionCommand({ + ConnectionId: connectionId, + Data: postData, + }) + const response = await apiClient.send(apiCommand); + console.log(JSON.stringify(response)); + + } catch (e) { + if (e.name === 'GoneException') { return; } + if (e.statusCode === 410) { + console.log(`Found stale connection, deleting ${connectionId}`); + const command = new DeleteCommand({ + TableName: process.env.TABLE_NAME, + Key: { connectionId }, + }); + + const response = await docClient.send(command); + console.log(JSON.stringify(response)); + } else { + throw e; + } + } + }); + + return { statusCode: 200, body: "Data sent." }; +}; diff --git a/examples/websocket/main.tf b/examples/websocket/main.tf index c6229b4..1587204 100644 --- a/examples/websocket/main.tf +++ b/examples/websocket/main.tf @@ -1,243 +1,243 @@ -provider "aws" { - region = local.region -} - -locals { - name = "ex-${basename(path.cwd)}" - region = "eu-west-1" - - dynamodb_table_name = local.name - dynamodb_crud_permissions = { - effect = "Allow", - actions = [ - "dynamodb:GetItem", - "dynamodb:DeleteItem", - "dynamodb:PutItem", - "dynamodb:Scan", - "dynamodb:Query", - "dynamodb:UpdateItem", - "dynamodb:BatchWriteItem", - "dynamodb:BatchGetItem", - "dynamodb:DescribeTable", - "dynamodb:ConditionCheckItem", - ], - resources = [ - module.dynamodb_table.dynamodb_table_arn, - "${module.dynamodb_table.dynamodb_table_arn}/index/*" - ] - } - - tags = { - Example = local.name - GithubRepo = "terraform-aws-apigateway-v2" - GithubOrg = "terraform-aws-modules" - } -} - -################################################################################ -# API Gateway Module -################################################################################ - -module "api_gateway" { - source = "../../" - - # API - description = "My awesome AWS Websocket API Gateway" - name = local.name - - # Custom Domain - create_domain_name = false - - # Websocket - protocol_type = "WEBSOCKET" - route_selection_expression = "$request.body.action" - - # Routes & Integration(s) - routes = { - "$connect" = { - operation_name = "ConnectRoute" - - integration = { - uri = module.connect_lambda_function.lambda_function_invoke_arn - } - }, - "$disconnect" = { - operation_name = "DisconnectRoute" - - integration = { - uri = module.disconnect_lambda_function.lambda_function_invoke_arn - } - }, - "sendmessage" = { - operation_name = "SendRoute" - - integration = { - uri = module.send_message_lambda_function.lambda_function_invoke_arn - } - }, - } - - # Stage - stage_name = "prod" - - stage_default_route_settings = { - data_trace_enabled = true - detailed_metrics_enabled = true - logging_level = "INFO" - throttling_burst_limit = 100 - throttling_rate_limit = 100 - } - - stage_access_log_settings = { - create_log_group = true - log_group_retention_in_days = 7 - format = jsonencode({ - context = { - domainName = "$context.domainName" - integrationErrorMessage = "$context.integrationErrorMessage" - protocol = "$context.protocol" - requestId = "$context.requestId" - requestTime = "$context.requestTime" - responseLength = "$context.responseLength" - routeKey = "$context.routeKey" - stage = "$context.stage" - status = "$context.status" - error = { - message = "$context.error.message" - responseType = "$context.error.responseType" - } - identity = { - sourceIP = "$context.identity.sourceIp" - } - integration = { - error = "$context.integration.error" - integrationStatus = "$context.integration.integrationStatus" - } - } - }) - } - - tags = local.tags -} - -################################################################################ -# Supporting Resources -################################################################################ - -module "connect_lambda_function" { - source = "terraform-aws-modules/lambda/aws" - version = "~> 4.0" - - function_name = "${local.name}-onConnect" - description = "Websocket onConnect handler" - source_path = ["function/onConnect.js"] - handler = "onConnect.handler" - runtime = "nodejs20.x" - architectures = ["arm64"] - memory_size = 256 - publish = true - - environment_variables = { - TABLE_NAME = module.dynamodb_table.dynamodb_table_id - } - - allowed_triggers = { - apigateway = { - service = "apigateway" - source_arn = "${module.api_gateway.api_execution_arn}/*/*" - } - } - - attach_policy_statements = true - policy_statements = { - dynamodb = local.dynamodb_crud_permissions - } - - tags = local.tags -} - -module "disconnect_lambda_function" { - source = "terraform-aws-modules/lambda/aws" - version = "~> 4.0" - - function_name = "${local.name}-onDisconnect" - description = "Websocket onDisconnect handler" - source_path = ["function/onDisconnect.js"] - handler = "onDisconnect.handler" - runtime = "nodejs20.x" - architectures = ["arm64"] - memory_size = 256 - publish = true - - environment_variables = { - TABLE_NAME = module.dynamodb_table.dynamodb_table_id - } - - allowed_triggers = { - apigateway = { - service = "apigateway" - source_arn = "${module.api_gateway.api_execution_arn}/*/*" - } - } - - attach_policy_statements = true - policy_statements = { - dynamodb = local.dynamodb_crud_permissions - } - - tags = local.tags -} - -module "send_message_lambda_function" { - source = "terraform-aws-modules/lambda/aws" - version = "~> 4.0" - - function_name = "${local.name}-sendMessage" - description = "Websocket sendMessage handler" - source_path = ["function/sendMessage.js"] - handler = "sendMessage.handler" - runtime = "nodejs20.x" - architectures = ["arm64"] - memory_size = 256 - publish = true - - environment_variables = { - TABLE_NAME = module.dynamodb_table.dynamodb_table_id - } - - allowed_triggers = { - apigateway = { - service = "apigateway" - source_arn = "${module.api_gateway.api_execution_arn}/*/*" - } - } - - attach_policy_statements = true - policy_statements = { - manage_connections = { - effect = "Allow", - actions = ["execute-api:ManageConnections"], - resources = ["${module.api_gateway.api_execution_arn}/*"] - } - dynamodb = local.dynamodb_crud_permissions - } - - tags = local.tags -} - -module "dynamodb_table" { - source = "terraform-aws-modules/dynamodb-table/aws" - version = "~> 3.0" - - name = local.dynamodb_table_name - hash_key = "connectionId" - - attributes = [ - { - name = "connectionId" - type = "S" - } - ] - - tags = local.tags -} +provider "aws" { + region = local.region +} + +locals { + name = "ex-${basename(path.cwd)}" + region = "eu-west-1" + + dynamodb_table_name = local.name + dynamodb_crud_permissions = { + effect = "Allow", + actions = [ + "dynamodb:GetItem", + "dynamodb:DeleteItem", + "dynamodb:PutItem", + "dynamodb:Scan", + "dynamodb:Query", + "dynamodb:UpdateItem", + "dynamodb:BatchWriteItem", + "dynamodb:BatchGetItem", + "dynamodb:DescribeTable", + "dynamodb:ConditionCheckItem", + ], + resources = [ + module.dynamodb_table.dynamodb_table_arn, + "${module.dynamodb_table.dynamodb_table_arn}/index/*" + ] + } + + tags = { + Example = local.name + GithubRepo = "terraform-aws-apigateway-v2" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# API Gateway Module +################################################################################ + +module "api_gateway" { + source = "../../" + + # API + description = "My awesome AWS Websocket API Gateway" + name = local.name + + # Custom Domain + create_domain_name = false + + # Websocket + protocol_type = "WEBSOCKET" + route_selection_expression = "$request.body.action" + + # Routes & Integration(s) + routes = { + "$connect" = { + operation_name = "ConnectRoute" + + integration = { + uri = module.connect_lambda_function.lambda_function_invoke_arn + } + }, + "$disconnect" = { + operation_name = "DisconnectRoute" + + integration = { + uri = module.disconnect_lambda_function.lambda_function_invoke_arn + } + }, + "sendmessage" = { + operation_name = "SendRoute" + + integration = { + uri = module.send_message_lambda_function.lambda_function_invoke_arn + } + }, + } + + # Stage + stage_name = "prod" + + stage_default_route_settings = { + data_trace_enabled = true + detailed_metrics_enabled = true + logging_level = "INFO" + throttling_burst_limit = 100 + throttling_rate_limit = 100 + } + + stage_access_log_settings = { + create_log_group = true + log_group_retention_in_days = 7 + format = jsonencode({ + context = { + domainName = "$context.domainName" + integrationErrorMessage = "$context.integrationErrorMessage" + protocol = "$context.protocol" + requestId = "$context.requestId" + requestTime = "$context.requestTime" + responseLength = "$context.responseLength" + routeKey = "$context.routeKey" + stage = "$context.stage" + status = "$context.status" + error = { + message = "$context.error.message" + responseType = "$context.error.responseType" + } + identity = { + sourceIP = "$context.identity.sourceIp" + } + integration = { + error = "$context.integration.error" + integrationStatus = "$context.integration.integrationStatus" + } + } + }) + } + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +module "connect_lambda_function" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 4.0" + + function_name = "${local.name}-onConnect" + description = "Websocket onConnect handler" + source_path = ["function/onConnect.js"] + handler = "onConnect.handler" + runtime = "nodejs20.x" + architectures = ["arm64"] + memory_size = 256 + publish = true + + environment_variables = { + TABLE_NAME = module.dynamodb_table.dynamodb_table_id + } + + allowed_triggers = { + apigateway = { + service = "apigateway" + source_arn = "${module.api_gateway.api_execution_arn}/*/*" + } + } + + attach_policy_statements = true + policy_statements = { + dynamodb = local.dynamodb_crud_permissions + } + + tags = local.tags +} + +module "disconnect_lambda_function" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 4.0" + + function_name = "${local.name}-onDisconnect" + description = "Websocket onDisconnect handler" + source_path = ["function/onDisconnect.js"] + handler = "onDisconnect.handler" + runtime = "nodejs20.x" + architectures = ["arm64"] + memory_size = 256 + publish = true + + environment_variables = { + TABLE_NAME = module.dynamodb_table.dynamodb_table_id + } + + allowed_triggers = { + apigateway = { + service = "apigateway" + source_arn = "${module.api_gateway.api_execution_arn}/*/*" + } + } + + attach_policy_statements = true + policy_statements = { + dynamodb = local.dynamodb_crud_permissions + } + + tags = local.tags +} + +module "send_message_lambda_function" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 4.0" + + function_name = "${local.name}-sendMessage" + description = "Websocket sendMessage handler" + source_path = ["function/sendMessage.js"] + handler = "sendMessage.handler" + runtime = "nodejs20.x" + architectures = ["arm64"] + memory_size = 256 + publish = true + + environment_variables = { + TABLE_NAME = module.dynamodb_table.dynamodb_table_id + } + + allowed_triggers = { + apigateway = { + service = "apigateway" + source_arn = "${module.api_gateway.api_execution_arn}/*/*" + } + } + + attach_policy_statements = true + policy_statements = { + manage_connections = { + effect = "Allow", + actions = ["execute-api:ManageConnections"], + resources = ["${module.api_gateway.api_execution_arn}/*"] + } + dynamodb = local.dynamodb_crud_permissions + } + + tags = local.tags +} + +module "dynamodb_table" { + source = "terraform-aws-modules/dynamodb-table/aws" + version = "~> 3.0" + + name = local.dynamodb_table_name + hash_key = "connectionId" + + attributes = [ + { + name = "connectionId" + type = "S" + } + ] + + tags = local.tags +} diff --git a/examples/websocket/outputs.tf b/examples/websocket/outputs.tf index 29e5677..00299b2 100644 --- a/examples/websocket/outputs.tf +++ b/examples/websocket/outputs.tf @@ -1,145 +1,145 @@ -################################################################################ -# API Gateway -################################################################################ - -output "api_id" { - description = "The API identifier" - value = module.api_gateway.api_id -} - -output "api_endpoint" { - description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" - value = module.api_gateway.api_endpoint -} - -output "api_arn" { - description = "The ARN of the API" - value = module.api_gateway.api_arn -} - -output "api_execution_arn" { - description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" - value = module.api_gateway.api_execution_arn -} - -################################################################################ -# Authorizer(s) -################################################################################ - -output "authorizers" { - description = "Map of API Gateway Authorizer(s) created and their attributes" - value = module.api_gateway.authorizers -} - -################################################################################ -# Domain Name -################################################################################ - -output "domain_name_id" { - description = "The domain name identifier" - value = module.api_gateway.domain_name_id -} - -output "stage_domain_name" { - description = "Domain name of the stage (useful for CloudFront distribution)" - value = module.api_gateway.stage_domain_name -} - -output "domain_name_arn" { - description = "The ARN of the domain name" - value = module.api_gateway.domain_name_arn -} - -output "domain_name_api_mapping_selection_expression" { - description = "The API mapping selection expression for the domain name" - value = module.api_gateway.domain_name_api_mapping_selection_expression -} - -output "domain_name_configuration" { - description = "The domain name configuration" - value = module.api_gateway.domain_name_configuration -} - -output "domain_name_target_domain_name" { - description = "The target domain name" - value = module.api_gateway.domain_name_target_domain_name -} - -output "domain_name_hosted_zone_id" { - description = "The Amazon Route 53 Hosted Zone ID of the endpoint" - value = module.api_gateway.domain_name_hosted_zone_id -} - -################################################################################ -# Domain - Certificate -################################################################################ - -output "acm_certificate_arn" { - description = "The ARN of the certificate" - value = module.api_gateway.acm_certificate_arn -} - -################################################################################ -# Integration(s) -################################################################################ - -output "integrations" { - description = "Map of the integrations created and their attributes" - value = module.api_gateway.integrations -} - -################################################################################ -# Route(s) -################################################################################ - -output "routes" { - description = "Map of the routes created and their attributes" - value = module.api_gateway.routes -} - -################################################################################ -# Stage -################################################################################ - -output "stage_id" { - description = "The stage identifier" - value = module.api_gateway.stage_id -} - -output "stage_arn" { - description = "The stage ARN" - value = module.api_gateway.stage_arn -} - -output "stage_execution_arn" { - description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" - value = module.api_gateway.stage_execution_arn -} - -output "stage_invoke_url" { - description = "The URL to invoke the API pointing to the stage" - value = module.api_gateway.stage_invoke_url -} - -################################################################################ -# Stage Access Logs - Log Group -################################################################################ - -output "stage_access_logs_cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name -} - -output "stage_access_logs_cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn -} - -################################################################################ -# VPC Link -################################################################################ - -output "vpc_links" { - description = "Map of VPC links created and their attributes" - value = module.api_gateway.vpc_links -} +################################################################################ +# API Gateway +################################################################################ + +output "api_id" { + description = "The API identifier" + value = module.api_gateway.api_id +} + +output "api_endpoint" { + description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" + value = module.api_gateway.api_endpoint +} + +output "api_arn" { + description = "The ARN of the API" + value = module.api_gateway.api_arn +} + +output "api_execution_arn" { + description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" + value = module.api_gateway.api_execution_arn +} + +################################################################################ +# Authorizer(s) +################################################################################ + +output "authorizers" { + description = "Map of API Gateway Authorizer(s) created and their attributes" + value = module.api_gateway.authorizers +} + +################################################################################ +# Domain Name +################################################################################ + +output "domain_name_id" { + description = "The domain name identifier" + value = module.api_gateway.domain_name_id +} + +output "stage_domain_name" { + description = "Domain name of the stage (useful for CloudFront distribution)" + value = module.api_gateway.stage_domain_name +} + +output "domain_name_arn" { + description = "The ARN of the domain name" + value = module.api_gateway.domain_name_arn +} + +output "domain_name_api_mapping_selection_expression" { + description = "The API mapping selection expression for the domain name" + value = module.api_gateway.domain_name_api_mapping_selection_expression +} + +output "domain_name_configuration" { + description = "The domain name configuration" + value = module.api_gateway.domain_name_configuration +} + +output "domain_name_target_domain_name" { + description = "The target domain name" + value = module.api_gateway.domain_name_target_domain_name +} + +output "domain_name_hosted_zone_id" { + description = "The Amazon Route 53 Hosted Zone ID of the endpoint" + value = module.api_gateway.domain_name_hosted_zone_id +} + +################################################################################ +# Domain - Certificate +################################################################################ + +output "acm_certificate_arn" { + description = "The ARN of the certificate" + value = module.api_gateway.acm_certificate_arn +} + +################################################################################ +# Integration(s) +################################################################################ + +output "integrations" { + description = "Map of the integrations created and their attributes" + value = module.api_gateway.integrations +} + +################################################################################ +# Route(s) +################################################################################ + +output "routes" { + description = "Map of the routes created and their attributes" + value = module.api_gateway.routes +} + +################################################################################ +# Stage +################################################################################ + +output "stage_id" { + description = "The stage identifier" + value = module.api_gateway.stage_id +} + +output "stage_arn" { + description = "The stage ARN" + value = module.api_gateway.stage_arn +} + +output "stage_execution_arn" { + description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" + value = module.api_gateway.stage_execution_arn +} + +output "stage_invoke_url" { + description = "The URL to invoke the API pointing to the stage" + value = module.api_gateway.stage_invoke_url +} + +################################################################################ +# Stage Access Logs - Log Group +################################################################################ + +output "stage_access_logs_cloudwatch_log_group_name" { + description = "Name of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_name +} + +output "stage_access_logs_cloudwatch_log_group_arn" { + description = "Arn of cloudwatch log group created" + value = module.api_gateway.stage_access_logs_cloudwatch_log_group_arn +} + +################################################################################ +# VPC Link +################################################################################ + +output "vpc_links" { + description = "Map of VPC links created and their attributes" + value = module.api_gateway.vpc_links +} diff --git a/examples/websocket/versions.tf b/examples/websocket/versions.tf index 97e1864..623b21b 100644 --- a/examples/websocket/versions.tf +++ b/examples/websocket/versions.tf @@ -1,10 +1,10 @@ -terraform { - required_version = ">= 1.3" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.96" - } - } -} +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.96" + } + } +} diff --git a/main.tf b/main.tf index bace49e..3b5f547 100644 --- a/main.tf +++ b/main.tf @@ -1,436 +1,436 @@ -locals { - is_http = var.protocol_type == "HTTP" - is_websocket = var.protocol_type == "WEBSOCKET" - - create_routes_and_integrations = var.create && var.create_routes_and_integrations -} - -################################################################################ -# API Gateway -################################################################################ - -resource "aws_apigatewayv2_api" "this" { - count = var.create ? 1 : 0 - - api_key_selection_expression = local.is_websocket ? var.api_key_selection_expression : null - body = local.is_http ? var.body : null - - dynamic "cors_configuration" { - for_each = local.is_http && var.cors_configuration != null ? [var.cors_configuration] : [] - - content { - allow_credentials = cors_configuration.value.allow_credentials - allow_headers = cors_configuration.value.allow_headers - allow_methods = cors_configuration.value.allow_methods - allow_origins = cors_configuration.value.allow_origins - expose_headers = cors_configuration.value.expose_headers - max_age = cors_configuration.value.max_age - } - } - - credentials_arn = local.is_http ? var.credentials_arn : null - description = var.description - # https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-disable-default-endpoint.html - disable_execute_api_endpoint = local.is_http && local.create_domain_name ? true : var.disable_execute_api_endpoint - fail_on_warnings = local.is_http ? var.fail_on_warnings : null - ip_address_type = var.ip_address_type - name = var.name - protocol_type = var.protocol_type - route_key = local.is_http ? var.route_key : null - route_selection_expression = var.route_selection_expression - target = local.is_http ? var.target : null - version = var.api_version - - tags = merge( - { terraform-aws-modules = "apigateway-v2" }, - var.tags, - ) -} - -################################################################################ -# Authorizer(s) -################################################################################ - -resource "aws_apigatewayv2_authorizer" "this" { - for_each = { for k, v in var.authorizers : k => v if var.create } - - api_id = aws_apigatewayv2_api.this[0].id - - authorizer_credentials_arn = each.value.authorizer_credentials_arn - authorizer_payload_format_version = each.value.authorizer_payload_format_version - authorizer_result_ttl_in_seconds = each.value.authorizer_result_ttl_in_seconds - authorizer_type = each.value.authorizer_type - authorizer_uri = each.value.authorizer_uri - enable_simple_responses = each.value.enable_simple_responses - identity_sources = each.value.identity_sources - - dynamic "jwt_configuration" { - for_each = each.value.jwt_configuration != null ? [each.value.jwt_configuration] : [] - - content { - audience = jwt_configuration.value.audience - issuer = jwt_configuration.value.issuer - } - } - - name = coalesce(each.value.name, each.key) -} - -################################################################################ -# Domain Name -################################################################################ - -locals { - create_domain_name = var.create && var.create_domain_name -} - -resource "aws_apigatewayv2_domain_name" "this" { - count = local.create_domain_name ? 1 : 0 - - domain_name = var.domain_name - - domain_name_configuration { - certificate_arn = local.create_certificate ? module.acm.acm_certificate_arn : var.domain_name_certificate_arn - endpoint_type = "REGIONAL" - ip_address_type = var.ip_address_type - security_policy = "TLS_1_2" - ownership_verification_certificate_arn = var.domain_name_ownership_verification_certificate_arn - } - - dynamic "mutual_tls_authentication" { - for_each = length(var.mutual_tls_authentication) > 0 ? [var.mutual_tls_authentication] : [] - - content { - truststore_uri = mutual_tls_authentication.value.truststore_uri - truststore_version = try(mutual_tls_authentication.value.truststore_version, null) - } - } - - tags = var.tags -} - -resource "aws_apigatewayv2_api_mapping" "this" { - count = local.create_domain_name && local.create_stage ? 1 : 0 - - api_id = aws_apigatewayv2_api.this[0].id - api_mapping_key = var.api_mapping_key - domain_name = aws_apigatewayv2_domain_name.this[0].id - stage = aws_apigatewayv2_stage.this[0].id -} - -################################################################################ -# Domain - Route53 Record -################################################################################ - -locals { - # https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html - stripped_domain_name = replace(var.domain_name, "*.", "") - - record_names = coalescelist(var.subdomains, [local.stripped_domain_name]) - record_set = { for prd in setproduct(local.record_names, var.subdomain_record_types) : "${prd[0]}-${prd[1]}" => { - name = prd[0] - type = prd[1] - } } -} - -data "aws_route53_zone" "this" { - count = local.create_domain_name && var.create_domain_records ? 1 : 0 - private_zone = var.private_zone - name = coalesce(var.hosted_zone_name, local.stripped_domain_name) -} - -resource "aws_route53_record" "this" { - for_each = { for k, v in local.record_set : k => v if local.create_domain_name && var.create_domain_records } - - zone_id = data.aws_route53_zone.this[0].zone_id - name = each.value.name - type = each.value.type - - alias { - name = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name - zone_id = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id - evaluate_target_health = false - } -} - -################################################################################ -# Domain - Certificate -################################################################################ - -locals { - create_certificate = local.create_domain_name && var.create_certificate - - is_wildcard = startswith(var.domain_name, "*.") -} - -module "acm" { - source = "terraform-aws-modules/acm/aws" - version = "5.0.1" - - create_certificate = local.create_domain_name && var.create_domain_records && local.create_certificate - - domain_name = local.stripped_domain_name - zone_id = try(data.aws_route53_zone.this[0].id, "") - subject_alternative_names = local.is_wildcard ? [var.domain_name] : [for sub in var.subdomains : "${sub}.${local.stripped_domain_name}"] - - validation_method = "DNS" - - tags = var.tags -} - -################################################################################ -# Route(s) -################################################################################ - -resource "aws_apigatewayv2_route" "this" { - for_each = { for k, v in var.routes : k => v if local.create_routes_and_integrations } - - api_id = aws_apigatewayv2_api.this[0].id - - api_key_required = local.is_websocket ? each.value.api_key_required : null - authorization_scopes = each.value.authorization_scopes - authorization_type = each.value.authorization_type - authorizer_id = try(aws_apigatewayv2_authorizer.this[each.value.authorizer_key].id, each.value.authorizer_id) - model_selection_expression = local.is_websocket ? each.value.model_selection_expression : null - operation_name = each.value.operation_name - request_models = local.is_websocket ? each.value.request_models : null - - dynamic "request_parameter" { - for_each = { for k, v in each.value.request_parameter : k => v if try(v.request_parameter_key, null) != null && local.is_websocket } - - content { - request_parameter_key = request_parameter.value.request_parameter_key - required = request_parameter.value.required - } - } - - route_key = each.key - route_response_selection_expression = local.is_websocket ? each.value.route_response_selection_expression : null - target = "integrations/${aws_apigatewayv2_integration.this[each.key].id}" -} - -################################################################################ -# Route Response(s) -################################################################################ - -resource "aws_apigatewayv2_route_response" "this" { - for_each = { for k, v in var.routes : k => v if local.create_routes_and_integrations && coalesce(v.route_response.create, false) } - - api_id = aws_apigatewayv2_api.this[0].id - model_selection_expression = each.value.route_response.model_selection_expression - response_models = each.value.route_response.response_models - route_id = aws_apigatewayv2_route.this[each.key].id - route_response_key = each.value.route_response.route_response_key -} - -################################################################################ -# Integration(s) -################################################################################ - -resource "aws_apigatewayv2_integration" "this" { - for_each = { for k, v in var.routes : k => v.integration if local.create_routes_and_integrations } - - api_id = aws_apigatewayv2_api.this[0].id - - connection_id = try(aws_apigatewayv2_vpc_link.this[each.value.vpc_link_key].id, each.value.connection_id) - connection_type = each.value.connection_type - content_handling_strategy = each.value.content_handling_strategy - credentials_arn = each.value.credentials_arn - description = each.value.description - integration_method = each.value.method - integration_subtype = each.value.subtype - integration_type = each.value.type - integration_uri = each.value.uri - passthrough_behavior = each.value.passthrough_behavior - payload_format_version = each.value.payload_format_version - request_parameters = each.value.request_parameters - request_templates = each.value.request_templates - - dynamic "response_parameters" { - for_each = coalesce(each.value.response_parameters, []) - - content { - mappings = response_parameters.value.mappings - status_code = response_parameters.value.status_code - } - } - - template_selection_expression = each.value.template_selection_expression - timeout_milliseconds = each.value.timeout_milliseconds - - dynamic "tls_config" { - for_each = each.value.tls_config != null && !local.is_websocket ? [each.value.tls_config] : [] - - content { - server_name_to_verify = try(tls_config.value.server_name_to_verify, null) - } - } - - lifecycle { - create_before_destroy = true - } -} - -################################################################################ -# Integration(s) Response -################################################################################ - -resource "aws_apigatewayv2_integration_response" "this" { - for_each = { for k, v in var.routes : k => v.integration if local.create_routes_and_integrations && v.integration.response.integration_response_key != null } - - api_id = aws_apigatewayv2_api.this[0].id - integration_id = aws_apigatewayv2_integration.this[each.key].id - - content_handling_strategy = each.value.response.content_handling_strategy - integration_response_key = each.value.response.integration_response_key - response_templates = each.value.response.response_templates - template_selection_expression = each.value.response.template_selection_expression -} - -################################################################################ -# Stage -################################################################################ - -locals { - create_stage = var.create && var.create_stage - - default_log_format = jsonencode({ - context = { - domainName = "$context.domainName" - integrationErrorMessage = "$context.integrationErrorMessage" - protocol = "$context.protocol" - requestId = "$context.requestId" - requestTime = "$context.requestTime" - responseLength = "$context.responseLength" - routeKey = "$context.routeKey" - stage = "$context.stage" - status = "$context.status" - error = { - message = "$context.error.message" - responseType = "$context.error.responseType" - } - identity = { - sourceIP = "$context.identity.sourceIp" - } - integration = { - error = "$context.integration.error" - integrationStatus = "$context.integration.integrationStatus" - } - } - }) -} - -resource "aws_apigatewayv2_stage" "this" { - count = local.create_stage ? 1 : 0 - - api_id = aws_apigatewayv2_api.this[0].id - - dynamic "access_log_settings" { - for_each = var.stage_access_log_settings != null ? [var.stage_access_log_settings] : [] - - content { - destination_arn = access_log_settings.value.create_log_group ? aws_cloudwatch_log_group.this["this"].arn : access_log_settings.value.destination_arn - format = coalesce(access_log_settings.value.format, local.default_log_format) - } - } - - auto_deploy = local.is_http ? true : null - client_certificate_id = local.is_websocket ? var.stage_client_certificate_id : null - - dynamic "default_route_settings" { - for_each = var.stage_default_route_settings != null ? [var.stage_default_route_settings] : [] - - content { - data_trace_enabled = local.is_websocket ? default_route_settings.value.data_trace_enabled : null - detailed_metrics_enabled = default_route_settings.value.detailed_metrics_enabled - logging_level = local.is_websocket ? default_route_settings.value.logging_level : null - throttling_burst_limit = default_route_settings.value.throttling_burst_limit - throttling_rate_limit = default_route_settings.value.throttling_rate_limit - } - } - - deployment_id = local.is_http ? null : try(aws_apigatewayv2_deployment.this[0].id, null) - description = var.stage_description - name = var.stage_name - - dynamic "route_settings" { - for_each = { for k, v in var.routes : k => v if var.create_routes_and_integrations } - - content { - data_trace_enabled = local.is_websocket ? coalesce(route_settings.value.data_trace_enabled, var.stage_default_route_settings.data_trace_enabled) : null - detailed_metrics_enabled = coalesce(route_settings.value.detailed_metrics_enabled, var.stage_default_route_settings.detailed_metrics_enabled) - logging_level = local.is_websocket ? coalesce(route_settings.value.logging_level, var.stage_default_route_settings.logging_level) : null - route_key = route_settings.key - throttling_burst_limit = coalesce(route_settings.value.throttling_burst_limit, var.stage_default_route_settings.throttling_burst_limit) - throttling_rate_limit = coalesce(route_settings.value.throttling_rate_limit, var.stage_default_route_settings.throttling_rate_limit) - } - } - - stage_variables = var.stage_variables - - tags = merge(var.tags, var.stage_tags) - - depends_on = [ - aws_apigatewayv2_route.this - ] -} - -################################################################################ -# Deployment -################################################################################ - -resource "aws_apigatewayv2_deployment" "this" { - count = local.create_stage && var.deploy_stage && !local.is_http ? 1 : 0 - - api_id = aws_apigatewayv2_api.this[0].id - description = var.description - - triggers = { - redeployment = sha1(join(",", tolist([ - jsonencode(aws_apigatewayv2_integration.this), - jsonencode(aws_apigatewayv2_route.this), - jsonencode(aws_apigatewayv2_route_response.this), - jsonencode(aws_apigatewayv2_api.this[0].body), - ]))) - } - - depends_on = [ - aws_apigatewayv2_api.this, - aws_apigatewayv2_route.this, - aws_apigatewayv2_integration.this, - ] - - lifecycle { - create_before_destroy = true - } -} - -################################################################################ -# Stage Access Logs - Log Group -################################################################################ - -resource "aws_cloudwatch_log_group" "this" { - for_each = { for k, v in { "this" = var.stage_access_log_settings } : k => v if local.create_stage && v != null && try(v.create_log_group, true) } - - name = coalesce(each.value.log_group_name, "/aws/apigateway/${var.name}/${replace(var.stage_name, "$", "")}") - retention_in_days = each.value.log_group_retention_in_days - kms_key_id = each.value.log_group_kms_key_id - skip_destroy = each.value.log_group_skip_destroy - log_group_class = each.value.log_group_class - - tags = merge(var.tags, each.value.log_group_tags) -} - -################################################################################ -# VPC Link -################################################################################ - -resource "aws_apigatewayv2_vpc_link" "this" { - for_each = { for k, v in var.vpc_links : k => v if var.create } - - name = coalesce(each.value.name, each.key) - security_group_ids = each.value.security_group_ids - subnet_ids = each.value.subnet_ids - - tags = merge(var.tags, var.vpc_link_tags, try(each.value.tags, {})) -} +locals { + is_http = var.protocol_type == "HTTP" + is_websocket = var.protocol_type == "WEBSOCKET" + + create_routes_and_integrations = var.create && var.create_routes_and_integrations +} + +################################################################################ +# API Gateway +################################################################################ + +resource "aws_apigatewayv2_api" "this" { + count = var.create ? 1 : 0 + + api_key_selection_expression = local.is_websocket ? var.api_key_selection_expression : null + body = local.is_http ? var.body : null + + dynamic "cors_configuration" { + for_each = local.is_http && var.cors_configuration != null ? [var.cors_configuration] : [] + + content { + allow_credentials = cors_configuration.value.allow_credentials + allow_headers = cors_configuration.value.allow_headers + allow_methods = cors_configuration.value.allow_methods + allow_origins = cors_configuration.value.allow_origins + expose_headers = cors_configuration.value.expose_headers + max_age = cors_configuration.value.max_age + } + } + + credentials_arn = local.is_http ? var.credentials_arn : null + description = var.description + # https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-disable-default-endpoint.html + disable_execute_api_endpoint = local.is_http && local.create_domain_name ? true : var.disable_execute_api_endpoint + fail_on_warnings = local.is_http ? var.fail_on_warnings : null + ip_address_type = var.ip_address_type + name = var.name + protocol_type = var.protocol_type + route_key = local.is_http ? var.route_key : null + route_selection_expression = var.route_selection_expression + target = local.is_http ? var.target : null + version = var.api_version + + tags = merge( + { terraform-aws-modules = "apigateway-v2" }, + var.tags, + ) +} + +################################################################################ +# Authorizer(s) +################################################################################ + +resource "aws_apigatewayv2_authorizer" "this" { + for_each = { for k, v in var.authorizers : k => v if var.create } + + api_id = aws_apigatewayv2_api.this[0].id + + authorizer_credentials_arn = each.value.authorizer_credentials_arn + authorizer_payload_format_version = each.value.authorizer_payload_format_version + authorizer_result_ttl_in_seconds = each.value.authorizer_result_ttl_in_seconds + authorizer_type = each.value.authorizer_type + authorizer_uri = each.value.authorizer_uri + enable_simple_responses = each.value.enable_simple_responses + identity_sources = each.value.identity_sources + + dynamic "jwt_configuration" { + for_each = each.value.jwt_configuration != null ? [each.value.jwt_configuration] : [] + + content { + audience = jwt_configuration.value.audience + issuer = jwt_configuration.value.issuer + } + } + + name = coalesce(each.value.name, each.key) +} + +################################################################################ +# Domain Name +################################################################################ + +locals { + create_domain_name = var.create && var.create_domain_name +} + +resource "aws_apigatewayv2_domain_name" "this" { + count = local.create_domain_name ? 1 : 0 + + domain_name = var.domain_name + + domain_name_configuration { + certificate_arn = local.create_certificate ? module.acm.acm_certificate_arn : var.domain_name_certificate_arn + endpoint_type = "REGIONAL" + ip_address_type = var.ip_address_type + security_policy = "TLS_1_2" + ownership_verification_certificate_arn = var.domain_name_ownership_verification_certificate_arn + } + + dynamic "mutual_tls_authentication" { + for_each = length(var.mutual_tls_authentication) > 0 ? [var.mutual_tls_authentication] : [] + + content { + truststore_uri = mutual_tls_authentication.value.truststore_uri + truststore_version = try(mutual_tls_authentication.value.truststore_version, null) + } + } + + tags = var.tags +} + +resource "aws_apigatewayv2_api_mapping" "this" { + count = local.create_domain_name && local.create_stage ? 1 : 0 + + api_id = aws_apigatewayv2_api.this[0].id + api_mapping_key = var.api_mapping_key + domain_name = aws_apigatewayv2_domain_name.this[0].id + stage = aws_apigatewayv2_stage.this[0].id +} + +################################################################################ +# Domain - Route53 Record +################################################################################ + +locals { + # https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html + stripped_domain_name = replace(var.domain_name, "*.", "") + + record_names = coalescelist(var.subdomains, [local.stripped_domain_name]) + record_set = { for prd in setproduct(local.record_names, var.subdomain_record_types) : "${prd[0]}-${prd[1]}" => { + name = prd[0] + type = prd[1] + } } +} + +data "aws_route53_zone" "this" { + count = local.create_domain_name && var.create_domain_records ? 1 : 0 + private_zone = var.private_zone + name = coalesce(var.hosted_zone_name, local.stripped_domain_name) +} + +resource "aws_route53_record" "this" { + for_each = { for k, v in local.record_set : k => v if local.create_domain_name && var.create_domain_records } + + zone_id = data.aws_route53_zone.this[0].zone_id + name = each.value.name + type = each.value.type + + alias { + name = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name + zone_id = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id + evaluate_target_health = false + } +} + +################################################################################ +# Domain - Certificate +################################################################################ + +locals { + create_certificate = local.create_domain_name && var.create_certificate + + is_wildcard = startswith(var.domain_name, "*.") +} + +module "acm" { + source = "terraform-aws-modules/acm/aws" + version = "5.0.1" + + create_certificate = local.create_domain_name && var.create_domain_records && local.create_certificate + + domain_name = local.stripped_domain_name + zone_id = try(data.aws_route53_zone.this[0].id, "") + subject_alternative_names = local.is_wildcard ? [var.domain_name] : [for sub in var.subdomains : "${sub}.${local.stripped_domain_name}"] + + validation_method = "DNS" + + tags = var.tags +} + +################################################################################ +# Route(s) +################################################################################ + +resource "aws_apigatewayv2_route" "this" { + for_each = { for k, v in var.routes : k => v if local.create_routes_and_integrations } + + api_id = aws_apigatewayv2_api.this[0].id + + api_key_required = local.is_websocket ? each.value.api_key_required : null + authorization_scopes = each.value.authorization_scopes + authorization_type = each.value.authorization_type + authorizer_id = try(aws_apigatewayv2_authorizer.this[each.value.authorizer_key].id, each.value.authorizer_id) + model_selection_expression = local.is_websocket ? each.value.model_selection_expression : null + operation_name = each.value.operation_name + request_models = local.is_websocket ? each.value.request_models : null + + dynamic "request_parameter" { + for_each = { for k, v in each.value.request_parameter : k => v if try(v.request_parameter_key, null) != null && local.is_websocket } + + content { + request_parameter_key = request_parameter.value.request_parameter_key + required = request_parameter.value.required + } + } + + route_key = each.key + route_response_selection_expression = local.is_websocket ? each.value.route_response_selection_expression : null + target = "integrations/${aws_apigatewayv2_integration.this[each.key].id}" +} + +################################################################################ +# Route Response(s) +################################################################################ + +resource "aws_apigatewayv2_route_response" "this" { + for_each = { for k, v in var.routes : k => v if local.create_routes_and_integrations && coalesce(v.route_response.create, false) } + + api_id = aws_apigatewayv2_api.this[0].id + model_selection_expression = each.value.route_response.model_selection_expression + response_models = each.value.route_response.response_models + route_id = aws_apigatewayv2_route.this[each.key].id + route_response_key = each.value.route_response.route_response_key +} + +################################################################################ +# Integration(s) +################################################################################ + +resource "aws_apigatewayv2_integration" "this" { + for_each = { for k, v in var.routes : k => v.integration if local.create_routes_and_integrations } + + api_id = aws_apigatewayv2_api.this[0].id + + connection_id = try(aws_apigatewayv2_vpc_link.this[each.value.vpc_link_key].id, each.value.connection_id) + connection_type = each.value.connection_type + content_handling_strategy = each.value.content_handling_strategy + credentials_arn = each.value.credentials_arn + description = each.value.description + integration_method = each.value.method + integration_subtype = each.value.subtype + integration_type = each.value.type + integration_uri = each.value.uri + passthrough_behavior = each.value.passthrough_behavior + payload_format_version = each.value.payload_format_version + request_parameters = each.value.request_parameters + request_templates = each.value.request_templates + + dynamic "response_parameters" { + for_each = coalesce(each.value.response_parameters, []) + + content { + mappings = response_parameters.value.mappings + status_code = response_parameters.value.status_code + } + } + + template_selection_expression = each.value.template_selection_expression + timeout_milliseconds = each.value.timeout_milliseconds + + dynamic "tls_config" { + for_each = each.value.tls_config != null && !local.is_websocket ? [each.value.tls_config] : [] + + content { + server_name_to_verify = try(tls_config.value.server_name_to_verify, null) + } + } + + lifecycle { + create_before_destroy = true + } +} + +################################################################################ +# Integration(s) Response +################################################################################ + +resource "aws_apigatewayv2_integration_response" "this" { + for_each = { for k, v in var.routes : k => v.integration if local.create_routes_and_integrations && v.integration.response.integration_response_key != null } + + api_id = aws_apigatewayv2_api.this[0].id + integration_id = aws_apigatewayv2_integration.this[each.key].id + + content_handling_strategy = each.value.response.content_handling_strategy + integration_response_key = each.value.response.integration_response_key + response_templates = each.value.response.response_templates + template_selection_expression = each.value.response.template_selection_expression +} + +################################################################################ +# Stage +################################################################################ + +locals { + create_stage = var.create && var.create_stage + + default_log_format = jsonencode({ + context = { + domainName = "$context.domainName" + integrationErrorMessage = "$context.integrationErrorMessage" + protocol = "$context.protocol" + requestId = "$context.requestId" + requestTime = "$context.requestTime" + responseLength = "$context.responseLength" + routeKey = "$context.routeKey" + stage = "$context.stage" + status = "$context.status" + error = { + message = "$context.error.message" + responseType = "$context.error.responseType" + } + identity = { + sourceIP = "$context.identity.sourceIp" + } + integration = { + error = "$context.integration.error" + integrationStatus = "$context.integration.integrationStatus" + } + } + }) +} + +resource "aws_apigatewayv2_stage" "this" { + count = local.create_stage ? 1 : 0 + + api_id = aws_apigatewayv2_api.this[0].id + + dynamic "access_log_settings" { + for_each = var.stage_access_log_settings != null ? [var.stage_access_log_settings] : [] + + content { + destination_arn = access_log_settings.value.create_log_group ? aws_cloudwatch_log_group.this["this"].arn : access_log_settings.value.destination_arn + format = coalesce(access_log_settings.value.format, local.default_log_format) + } + } + + auto_deploy = local.is_http ? true : null + client_certificate_id = local.is_websocket ? var.stage_client_certificate_id : null + + dynamic "default_route_settings" { + for_each = var.stage_default_route_settings != null ? [var.stage_default_route_settings] : [] + + content { + data_trace_enabled = local.is_websocket ? default_route_settings.value.data_trace_enabled : null + detailed_metrics_enabled = default_route_settings.value.detailed_metrics_enabled + logging_level = local.is_websocket ? default_route_settings.value.logging_level : null + throttling_burst_limit = default_route_settings.value.throttling_burst_limit + throttling_rate_limit = default_route_settings.value.throttling_rate_limit + } + } + + deployment_id = local.is_http ? null : try(aws_apigatewayv2_deployment.this[0].id, null) + description = var.stage_description + name = var.stage_name + + dynamic "route_settings" { + for_each = { for k, v in var.routes : k => v if var.create_routes_and_integrations } + + content { + data_trace_enabled = local.is_websocket ? coalesce(route_settings.value.data_trace_enabled, var.stage_default_route_settings.data_trace_enabled) : null + detailed_metrics_enabled = coalesce(route_settings.value.detailed_metrics_enabled, var.stage_default_route_settings.detailed_metrics_enabled) + logging_level = local.is_websocket ? coalesce(route_settings.value.logging_level, var.stage_default_route_settings.logging_level) : null + route_key = route_settings.key + throttling_burst_limit = coalesce(route_settings.value.throttling_burst_limit, var.stage_default_route_settings.throttling_burst_limit) + throttling_rate_limit = coalesce(route_settings.value.throttling_rate_limit, var.stage_default_route_settings.throttling_rate_limit) + } + } + + stage_variables = var.stage_variables + + tags = merge(var.tags, var.stage_tags) + + depends_on = [ + aws_apigatewayv2_route.this + ] +} + +################################################################################ +# Deployment +################################################################################ + +resource "aws_apigatewayv2_deployment" "this" { + count = local.create_stage && var.deploy_stage && !local.is_http ? 1 : 0 + + api_id = aws_apigatewayv2_api.this[0].id + description = var.description + + triggers = { + redeployment = sha1(join(",", tolist([ + jsonencode(aws_apigatewayv2_integration.this), + jsonencode(aws_apigatewayv2_route.this), + jsonencode(aws_apigatewayv2_route_response.this), + jsonencode(aws_apigatewayv2_api.this[0].body), + ]))) + } + + depends_on = [ + aws_apigatewayv2_api.this, + aws_apigatewayv2_route.this, + aws_apigatewayv2_integration.this, + ] + + lifecycle { + create_before_destroy = true + } +} + +################################################################################ +# Stage Access Logs - Log Group +################################################################################ + +resource "aws_cloudwatch_log_group" "this" { + for_each = { for k, v in { "this" = var.stage_access_log_settings } : k => v if local.create_stage && v != null && try(v.create_log_group, true) } + + name = coalesce(each.value.log_group_name, "/aws/apigateway/${var.name}/${replace(var.stage_name, "$", "")}") + retention_in_days = each.value.log_group_retention_in_days + kms_key_id = each.value.log_group_kms_key_id + skip_destroy = each.value.log_group_skip_destroy + log_group_class = each.value.log_group_class + + tags = merge(var.tags, each.value.log_group_tags) +} + +################################################################################ +# VPC Link +################################################################################ + +resource "aws_apigatewayv2_vpc_link" "this" { + for_each = { for k, v in var.vpc_links : k => v if var.create } + + name = coalesce(each.value.name, each.key) + security_group_ids = each.value.security_group_ids + subnet_ids = each.value.subnet_ids + + tags = merge(var.tags, var.vpc_link_tags, try(each.value.tags, {})) +} diff --git a/migrations.tf b/migrations.tf index 698d523..ed78224 100644 --- a/migrations.tf +++ b/migrations.tf @@ -1,13 +1,13 @@ -################################################################################ -# Migrations: v4.0.0 -> v5.0.0 -################################################################################ - -moved { - from = aws_apigatewayv2_stage.default - to = aws_apigatewayv2_stage.this -} - -moved { - from = aws_cloudwatch_log_group.this[0] - to = aws_cloudwatch_log_group.this["this"] -} +################################################################################ +# Migrations: v4.0.0 -> v5.0.0 +################################################################################ + +moved { + from = aws_apigatewayv2_stage.default + to = aws_apigatewayv2_stage.this +} + +moved { + from = aws_cloudwatch_log_group.this[0] + to = aws_cloudwatch_log_group.this["this"] +} diff --git a/outputs.tf b/outputs.tf index 1188682..ce5a3cb 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,145 +1,145 @@ -################################################################################ -# API Gateway -################################################################################ - -output "api_id" { - description = "The API identifier" - value = try(aws_apigatewayv2_api.this[0].id, null) -} - -output "api_endpoint" { - description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" - value = try(aws_apigatewayv2_api.this[0].api_endpoint, null) -} - -output "api_arn" { - description = "The ARN of the API" - value = try(aws_apigatewayv2_api.this[0].arn, null) -} - -output "api_execution_arn" { - description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" - value = try(aws_apigatewayv2_api.this[0].execution_arn, null) -} - -################################################################################ -# Authorizer(s) -################################################################################ - -output "authorizers" { - description = "Map of API Gateway Authorizer(s) created and their attributes" - value = aws_apigatewayv2_authorizer.this -} - -################################################################################ -# Domain Name -################################################################################ - -output "domain_name_id" { - description = "The domain name identifier" - value = try(aws_apigatewayv2_domain_name.this[0].id, null) -} - -output "domain_name_arn" { - description = "The ARN of the domain name" - value = try(aws_apigatewayv2_domain_name.this[0].arn, null) -} - -output "domain_name_api_mapping_selection_expression" { - description = "The API mapping selection expression for the domain name" - value = try(aws_apigatewayv2_domain_name.this[0].api_mapping_selection_expression, null) -} - -output "domain_name_configuration" { - description = "The domain name configuration" - value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration, null) -} - -output "domain_name_target_domain_name" { - description = "The target domain name" - value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name, null) -} - -output "domain_name_hosted_zone_id" { - description = "The Amazon Route 53 Hosted Zone ID of the endpoint" - value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id, null) -} - -################################################################################ -# Domain - Certificate -################################################################################ - -output "acm_certificate_arn" { - description = "The ARN of the certificate" - value = module.acm.acm_certificate_arn -} - -################################################################################ -# Integration(s) -################################################################################ - -output "integrations" { - description = "Map of the integrations created and their attributes" - value = aws_apigatewayv2_integration.this -} - -################################################################################ -# Route(s) -################################################################################ - -output "routes" { - description = "Map of the routes created and their attributes" - value = aws_apigatewayv2_route.this -} - -################################################################################ -# Stage -################################################################################ - -output "stage_id" { - description = "The stage identifier" - value = try(aws_apigatewayv2_stage.this[0].id, null) -} - -output "stage_domain_name" { - description = "Domain name of the stage (useful for CloudFront distribution)" - value = replace(try(aws_apigatewayv2_stage.this[0].invoke_url, ""), "/^(wss?|https?)://([^/]*).*/", "$2") -} - -output "stage_arn" { - description = "The stage ARN" - value = try(aws_apigatewayv2_stage.this[0].arn, null) -} - -output "stage_execution_arn" { - description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" - value = try(aws_apigatewayv2_stage.this[0].execution_arn, null) -} - -output "stage_invoke_url" { - description = "The URL to invoke the API pointing to the stage" - value = try(aws_apigatewayv2_stage.this[0].invoke_url, null) -} - -################################################################################ -# Stage Access Logs - Log Group -################################################################################ - -output "stage_access_logs_cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = try(aws_cloudwatch_log_group.this[0].name, null) -} - -output "stage_access_logs_cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = try(aws_cloudwatch_log_group.this[0].arn, null) -} - -################################################################################ -# VPC Link -################################################################################ - -output "vpc_links" { - description = "Map of VPC links created and their attributes" - value = aws_apigatewayv2_vpc_link.this -} +################################################################################ +# API Gateway +################################################################################ + +output "api_id" { + description = "The API identifier" + value = try(aws_apigatewayv2_api.this[0].id, null) +} + +output "api_endpoint" { + description = "URI of the API, of the form `https://{api-id}.execute-api.{region}.amazonaws.com` for HTTP APIs and `wss://{api-id}.execute-api.{region}.amazonaws.com` for WebSocket APIs" + value = try(aws_apigatewayv2_api.this[0].api_endpoint, null) +} + +output "api_arn" { + description = "The ARN of the API" + value = try(aws_apigatewayv2_api.this[0].arn, null) +} + +output "api_execution_arn" { + description = "The ARN prefix to be used in an `aws_lambda_permission`'s `source_arn` attribute or in an `aws_iam_policy` to authorize access to the `@connections` API" + value = try(aws_apigatewayv2_api.this[0].execution_arn, null) +} + +################################################################################ +# Authorizer(s) +################################################################################ + +output "authorizers" { + description = "Map of API Gateway Authorizer(s) created and their attributes" + value = aws_apigatewayv2_authorizer.this +} + +################################################################################ +# Domain Name +################################################################################ + +output "domain_name_id" { + description = "The domain name identifier" + value = try(aws_apigatewayv2_domain_name.this[0].id, null) +} + +output "domain_name_arn" { + description = "The ARN of the domain name" + value = try(aws_apigatewayv2_domain_name.this[0].arn, null) +} + +output "domain_name_api_mapping_selection_expression" { + description = "The API mapping selection expression for the domain name" + value = try(aws_apigatewayv2_domain_name.this[0].api_mapping_selection_expression, null) +} + +output "domain_name_configuration" { + description = "The domain name configuration" + value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration, null) +} + +output "domain_name_target_domain_name" { + description = "The target domain name" + value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name, null) +} + +output "domain_name_hosted_zone_id" { + description = "The Amazon Route 53 Hosted Zone ID of the endpoint" + value = try(aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id, null) +} + +################################################################################ +# Domain - Certificate +################################################################################ + +output "acm_certificate_arn" { + description = "The ARN of the certificate" + value = module.acm.acm_certificate_arn +} + +################################################################################ +# Integration(s) +################################################################################ + +output "integrations" { + description = "Map of the integrations created and their attributes" + value = aws_apigatewayv2_integration.this +} + +################################################################################ +# Route(s) +################################################################################ + +output "routes" { + description = "Map of the routes created and their attributes" + value = aws_apigatewayv2_route.this +} + +################################################################################ +# Stage +################################################################################ + +output "stage_id" { + description = "The stage identifier" + value = try(aws_apigatewayv2_stage.this[0].id, null) +} + +output "stage_domain_name" { + description = "Domain name of the stage (useful for CloudFront distribution)" + value = replace(try(aws_apigatewayv2_stage.this[0].invoke_url, ""), "/^(wss?|https?)://([^/]*).*/", "$2") +} + +output "stage_arn" { + description = "The stage ARN" + value = try(aws_apigatewayv2_stage.this[0].arn, null) +} + +output "stage_execution_arn" { + description = "The ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API" + value = try(aws_apigatewayv2_stage.this[0].execution_arn, null) +} + +output "stage_invoke_url" { + description = "The URL to invoke the API pointing to the stage" + value = try(aws_apigatewayv2_stage.this[0].invoke_url, null) +} + +################################################################################ +# Stage Access Logs - Log Group +################################################################################ + +output "stage_access_logs_cloudwatch_log_group_name" { + description = "Name of cloudwatch log group created" + value = try(aws_cloudwatch_log_group.this[0].name, null) +} + +output "stage_access_logs_cloudwatch_log_group_arn" { + description = "Arn of cloudwatch log group created" + value = try(aws_cloudwatch_log_group.this[0].arn, null) +} + +################################################################################ +# VPC Link +################################################################################ + +output "vpc_links" { + description = "Map of VPC links created and their attributes" + value = aws_apigatewayv2_vpc_link.this +} diff --git a/variables.tf b/variables.tf index 3663017..820b074 100644 --- a/variables.tf +++ b/variables.tf @@ -1,393 +1,393 @@ -variable "create" { - description = "Controls if resources should be created" - type = bool - default = true -} - -variable "tags" { - description = "A mapping of tags to assign to API gateway resources" - type = map(string) - default = {} -} - -################################################################################ -# API Gateway -################################################################################ - -variable "api_key_selection_expression" { - description = "An API key selection expression. Valid values: `$context.authorizer.usageIdentifierKey`, `$request.header.x-api-key`. Defaults to `$request.header.x-api-key`. Applicable for WebSocket APIs" - type = string - default = null -} - -variable "cors_configuration" { - description = "The cross-origin resource sharing (CORS) configuration. Applicable for HTTP APIs" - type = object({ - allow_credentials = optional(bool) - allow_headers = optional(list(string)) - allow_methods = optional(list(string)) - allow_origins = optional(list(string)) - expose_headers = optional(list(string), []) - max_age = optional(number) - }) - default = null -} - -variable "credentials_arn" { - description = "Part of quick create. Specifies any credentials required for the integration. Applicable for HTTP APIs" - type = string - default = null -} - -variable "description" { - description = "The description of the API. Must be less than or equal to 1024 characters in length" - type = string - default = null -} - -variable "disable_execute_api_endpoint" { - description = "Whether clients can invoke the API by using the default execute-api endpoint. By default, clients can invoke the API with the default `{api_id}.execute-api.{region}.amazonaws.com endpoint`. To require that clients use a custom domain name to invoke the API, disable the default endpoint" - type = bool - default = null -} - -variable "fail_on_warnings" { - description = "Whether warnings should return an error while API Gateway is creating or updating the resource using an OpenAPI specification. Defaults to `false`. Applicable for HTTP APIs" - type = bool - default = null -} - -variable "ip_address_type" { - description = "The IP address types that can invoke the API. Valid values: ipv4, dualstack. Use ipv4 to allow only IPv4 addresses to invoke your API, or use dualstack to allow both IPv4 and IPv6 addresses to invoke your API. Defaults to ipv4." - type = string - default = null -} - -variable "name" { - description = "The name of the API. Must be less than or equal to 128 characters in length" - type = string - default = "" -} - -variable "body" { - description = "An OpenAPI specification that defines the set of routes and integrations to create as part of the HTTP APIs. Supported only for HTTP APIs" - type = string - default = null -} - -variable "protocol_type" { - description = "The API protocol. Valid values: `HTTP`, `WEBSOCKET`" - type = string - default = "HTTP" -} - -variable "route_key" { - description = "Part of quick create. Specifies any route key. Applicable for HTTP APIs" - type = string - default = null -} - -variable "route_selection_expression" { - description = "The route selection expression for the API. Defaults to `$request.method $request.path`" - type = string - default = null -} - -variable "target" { - description = "Part of quick create. Quick create produces an API with an integration, a default catch-all route, and a default stage which is configured to automatically deploy changes. For HTTP integrations, specify a fully qualified URL. For Lambda integrations, specify a function ARN. The type of the integration will be HTTP_PROXY or AWS_PROXY, respectively. Applicable for HTTP APIs" - type = string - default = null -} - -variable "api_version" { - description = "A version identifier for the API. Must be between 1 and 64 characters in length" - type = string - default = null -} - -variable "api_mapping_key" { - description = "The [API mapping key](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-mapping-template-reference.html)" - type = string - default = null -} - -################################################################################ -# Authorizer(s) -################################################################################ - -variable "authorizers" { - description = "Map of API gateway authorizers to create" - type = map(object({ - authorizer_credentials_arn = optional(string) - authorizer_payload_format_version = optional(string) - authorizer_result_ttl_in_seconds = optional(number) - authorizer_type = optional(string, "REQUEST") - authorizer_uri = optional(string) - enable_simple_responses = optional(bool) - identity_sources = optional(list(string)) - jwt_configuration = optional(object({ - audience = optional(list(string)) - issuer = optional(string) - })) - name = optional(string) - })) - default = {} -} - -################################################################################ -# Domain Name -################################################################################ - -variable "create_domain_name" { - description = "Whether to create API domain name resource" - type = bool - default = true -} - -variable "domain_name" { - description = "The domain name to use for API gateway" - type = string - default = "" -} - -variable "hosted_zone_name" { - description = "Optional domain name of the Hosted Zone where the domain should be created" - type = string - default = null -} - -variable "private_zone" { - description = "Whether the hosted zone is private or not" - type = bool - default = false -} - -variable "domain_name_certificate_arn" { - description = "The ARN of an AWS-managed certificate that will be used by the endpoint for the domain name. AWS Certificate Manager is the only supported source" - type = string - default = null -} - -variable "domain_name_ownership_verification_certificate_arn" { - description = "ARN of the AWS-issued certificate used to validate custom domain ownership (when certificate_arn is issued via an ACM Private CA or mutual_tls_authentication is configured with an ACM-imported certificate.)" - type = string - default = null -} - -variable "mutual_tls_authentication" { - description = "The mutual TLS authentication configuration for the domain name" - type = map(string) - default = {} -} - -################################################################################ -# Domain - Route53 Record -################################################################################ - -variable "create_domain_records" { - description = "Whether to create Route53 records for the domain name" - type = bool - default = true -} - -variable "subdomains" { - description = "An optional list of subdomains to use for API gateway" - type = list(string) - default = [] -} - -variable "subdomain_record_types" { - description = "A list of record types to create for the subdomain(s)" - type = list(string) - default = ["A", "AAAA"] -} - -################################################################################ -# Domain - Certificate -################################################################################ - -variable "create_certificate" { - description = "Whether to create a certificate for the domain" - type = bool - default = true -} - -################################################################################ -# Route(s) & Integration(s) -################################################################################ - -variable "create_routes_and_integrations" { - description = "Whether to create routes and integrations resources" - type = bool - default = true -} - -variable "routes" { - description = "Map of API gateway routes with integrations" - type = map(object({ - # Route - authorizer_key = optional(string) - api_key_required = optional(bool) - authorization_scopes = optional(list(string), []) - authorization_type = optional(string) - authorizer_id = optional(string) - model_selection_expression = optional(string) - operation_name = optional(string) - request_models = optional(map(string), {}) - request_parameter = optional(object({ - request_parameter_key = optional(string) - required = optional(bool, false) - }), {}) - route_response_selection_expression = optional(string) - - # Route settings - data_trace_enabled = optional(bool) - detailed_metrics_enabled = optional(bool) - logging_level = optional(string) - throttling_burst_limit = optional(number) - throttling_rate_limit = optional(number) - - # Stage - Route response - route_response = optional(object({ - create = optional(bool, false) - model_selection_expression = optional(string) - response_models = optional(map(string)) - route_response_key = optional(string, "$default") - }), {}) - - # Integration - integration = object({ - connection_id = optional(string) - vpc_link_key = optional(string) - connection_type = optional(string) - content_handling_strategy = optional(string) - credentials_arn = optional(string) - description = optional(string) - method = optional(string) - subtype = optional(string) - type = optional(string, "AWS_PROXY") - uri = optional(string) - passthrough_behavior = optional(string) - payload_format_version = optional(string) - request_parameters = optional(map(string), {}) - request_templates = optional(map(string), {}) - response_parameters = optional(list(object({ - mappings = map(string) - status_code = string - }))) - template_selection_expression = optional(string) - timeout_milliseconds = optional(number) - tls_config = optional(object({ - server_name_to_verify = optional(string) - })) - - # Integration Response - response = optional(object({ - content_handling_strategy = optional(string) - integration_response_key = optional(string) - response_templates = optional(map(string)) - template_selection_expression = optional(string) - }), {}) - }) - })) - default = {} -} - -################################################################################ -# Stage -################################################################################ - -variable "create_stage" { - description = "Whether to create default stage" - type = bool - default = true -} - -variable "stage_access_log_settings" { - description = "Settings for logging access in this stage. Use the aws_api_gateway_account resource to configure [permissions for CloudWatch Logging](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html#set-up-access-logging-permissions)" - type = object({ - create_log_group = optional(bool, true) - destination_arn = optional(string) - format = optional(string) - log_group_name = optional(string) - log_group_retention_in_days = optional(number, 30) - log_group_kms_key_id = optional(string) - log_group_skip_destroy = optional(bool) - log_group_class = optional(string) - log_group_tags = optional(map(string), {}) - }) - default = {} -} - -variable "stage_client_certificate_id" { - description = "The identifier of a client certificate for the stage. Use the `aws_api_gateway_client_certificate` resource to configure a client certificate. Supported only for WebSocket APIs" - type = string - default = null -} - -variable "stage_default_route_settings" { - description = "The default route settings for the stage" - type = object({ - data_trace_enabled = optional(bool, true) - detailed_metrics_enabled = optional(bool, true) - logging_level = optional(string) - throttling_burst_limit = optional(number, 500) - throttling_rate_limit = optional(number, 1000) - }) - default = {} -} - -variable "stage_description" { - description = "The description for the stage. Must be less than or equal to 1024 characters in length" - type = string - default = null -} - -variable "stage_name" { - description = "The name of the stage. Must be between 1 and 128 characters in length" - type = string - default = "$default" -} - -variable "stage_variables" { - description = "A map that defines the stage variables for the stage" - type = map(string) - default = {} -} - -variable "stage_tags" { - description = "A mapping of tags to assign to the stage resource" - type = map(string) - default = {} -} - -################################################################################ -# Deployment -################################################################################ - -variable "deploy_stage" { - description = "Whether to deploy the stage. `HTTP` APIs are auto-deployed by default" - type = bool - default = true -} - -################################################################################ -# VPC Link -################################################################################ - -variable "vpc_links" { - description = "Map of VPC Link definitions to create" - type = map(object({ - name = optional(string) - security_group_ids = optional(list(string)) - subnet_ids = optional(list(string)) - tags = optional(map(string), {}) - })) - default = {} -} - -variable "vpc_link_tags" { - description = "A map of tags to add to the VPC Links created" - type = map(string) - default = {} -} +variable "create" { + description = "Controls if resources should be created" + type = bool + default = true +} + +variable "tags" { + description = "A mapping of tags to assign to API gateway resources" + type = map(string) + default = {} +} + +################################################################################ +# API Gateway +################################################################################ + +variable "api_key_selection_expression" { + description = "An API key selection expression. Valid values: `$context.authorizer.usageIdentifierKey`, `$request.header.x-api-key`. Defaults to `$request.header.x-api-key`. Applicable for WebSocket APIs" + type = string + default = null +} + +variable "cors_configuration" { + description = "The cross-origin resource sharing (CORS) configuration. Applicable for HTTP APIs" + type = object({ + allow_credentials = optional(bool) + allow_headers = optional(list(string)) + allow_methods = optional(list(string)) + allow_origins = optional(list(string)) + expose_headers = optional(list(string), []) + max_age = optional(number) + }) + default = null +} + +variable "credentials_arn" { + description = "Part of quick create. Specifies any credentials required for the integration. Applicable for HTTP APIs" + type = string + default = null +} + +variable "description" { + description = "The description of the API. Must be less than or equal to 1024 characters in length" + type = string + default = null +} + +variable "disable_execute_api_endpoint" { + description = "Whether clients can invoke the API by using the default execute-api endpoint. By default, clients can invoke the API with the default `{api_id}.execute-api.{region}.amazonaws.com endpoint`. To require that clients use a custom domain name to invoke the API, disable the default endpoint" + type = bool + default = null +} + +variable "fail_on_warnings" { + description = "Whether warnings should return an error while API Gateway is creating or updating the resource using an OpenAPI specification. Defaults to `false`. Applicable for HTTP APIs" + type = bool + default = null +} + +variable "ip_address_type" { + description = "The IP address types that can invoke the API. Valid values: ipv4, dualstack. Use ipv4 to allow only IPv4 addresses to invoke your API, or use dualstack to allow both IPv4 and IPv6 addresses to invoke your API. Defaults to ipv4." + type = string + default = null +} + +variable "name" { + description = "The name of the API. Must be less than or equal to 128 characters in length" + type = string + default = "" +} + +variable "body" { + description = "An OpenAPI specification that defines the set of routes and integrations to create as part of the HTTP APIs. Supported only for HTTP APIs" + type = string + default = null +} + +variable "protocol_type" { + description = "The API protocol. Valid values: `HTTP`, `WEBSOCKET`" + type = string + default = "HTTP" +} + +variable "route_key" { + description = "Part of quick create. Specifies any route key. Applicable for HTTP APIs" + type = string + default = null +} + +variable "route_selection_expression" { + description = "The route selection expression for the API. Defaults to `$request.method $request.path`" + type = string + default = null +} + +variable "target" { + description = "Part of quick create. Quick create produces an API with an integration, a default catch-all route, and a default stage which is configured to automatically deploy changes. For HTTP integrations, specify a fully qualified URL. For Lambda integrations, specify a function ARN. The type of the integration will be HTTP_PROXY or AWS_PROXY, respectively. Applicable for HTTP APIs" + type = string + default = null +} + +variable "api_version" { + description = "A version identifier for the API. Must be between 1 and 64 characters in length" + type = string + default = null +} + +variable "api_mapping_key" { + description = "The [API mapping key](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-mapping-template-reference.html)" + type = string + default = null +} + +################################################################################ +# Authorizer(s) +################################################################################ + +variable "authorizers" { + description = "Map of API gateway authorizers to create" + type = map(object({ + authorizer_credentials_arn = optional(string) + authorizer_payload_format_version = optional(string) + authorizer_result_ttl_in_seconds = optional(number) + authorizer_type = optional(string, "REQUEST") + authorizer_uri = optional(string) + enable_simple_responses = optional(bool) + identity_sources = optional(list(string)) + jwt_configuration = optional(object({ + audience = optional(list(string)) + issuer = optional(string) + })) + name = optional(string) + })) + default = {} +} + +################################################################################ +# Domain Name +################################################################################ + +variable "create_domain_name" { + description = "Whether to create API domain name resource" + type = bool + default = true +} + +variable "domain_name" { + description = "The domain name to use for API gateway" + type = string + default = "" +} + +variable "hosted_zone_name" { + description = "Optional domain name of the Hosted Zone where the domain should be created" + type = string + default = null +} + +variable "private_zone" { + description = "Whether the hosted zone is private or not" + type = bool + default = false +} + +variable "domain_name_certificate_arn" { + description = "The ARN of an AWS-managed certificate that will be used by the endpoint for the domain name. AWS Certificate Manager is the only supported source" + type = string + default = null +} + +variable "domain_name_ownership_verification_certificate_arn" { + description = "ARN of the AWS-issued certificate used to validate custom domain ownership (when certificate_arn is issued via an ACM Private CA or mutual_tls_authentication is configured with an ACM-imported certificate.)" + type = string + default = null +} + +variable "mutual_tls_authentication" { + description = "The mutual TLS authentication configuration for the domain name" + type = map(string) + default = {} +} + +################################################################################ +# Domain - Route53 Record +################################################################################ + +variable "create_domain_records" { + description = "Whether to create Route53 records for the domain name" + type = bool + default = true +} + +variable "subdomains" { + description = "An optional list of subdomains to use for API gateway" + type = list(string) + default = [] +} + +variable "subdomain_record_types" { + description = "A list of record types to create for the subdomain(s)" + type = list(string) + default = ["A", "AAAA"] +} + +################################################################################ +# Domain - Certificate +################################################################################ + +variable "create_certificate" { + description = "Whether to create a certificate for the domain" + type = bool + default = true +} + +################################################################################ +# Route(s) & Integration(s) +################################################################################ + +variable "create_routes_and_integrations" { + description = "Whether to create routes and integrations resources" + type = bool + default = true +} + +variable "routes" { + description = "Map of API gateway routes with integrations" + type = map(object({ + # Route + authorizer_key = optional(string) + api_key_required = optional(bool) + authorization_scopes = optional(list(string), []) + authorization_type = optional(string) + authorizer_id = optional(string) + model_selection_expression = optional(string) + operation_name = optional(string) + request_models = optional(map(string), {}) + request_parameter = optional(object({ + request_parameter_key = optional(string) + required = optional(bool, false) + }), {}) + route_response_selection_expression = optional(string) + + # Route settings + data_trace_enabled = optional(bool) + detailed_metrics_enabled = optional(bool) + logging_level = optional(string) + throttling_burst_limit = optional(number) + throttling_rate_limit = optional(number) + + # Stage - Route response + route_response = optional(object({ + create = optional(bool, false) + model_selection_expression = optional(string) + response_models = optional(map(string)) + route_response_key = optional(string, "$default") + }), {}) + + # Integration + integration = object({ + connection_id = optional(string) + vpc_link_key = optional(string) + connection_type = optional(string) + content_handling_strategy = optional(string) + credentials_arn = optional(string) + description = optional(string) + method = optional(string) + subtype = optional(string) + type = optional(string, "AWS_PROXY") + uri = optional(string) + passthrough_behavior = optional(string) + payload_format_version = optional(string) + request_parameters = optional(map(string), {}) + request_templates = optional(map(string), {}) + response_parameters = optional(list(object({ + mappings = map(string) + status_code = string + }))) + template_selection_expression = optional(string) + timeout_milliseconds = optional(number) + tls_config = optional(object({ + server_name_to_verify = optional(string) + })) + + # Integration Response + response = optional(object({ + content_handling_strategy = optional(string) + integration_response_key = optional(string) + response_templates = optional(map(string)) + template_selection_expression = optional(string) + }), {}) + }) + })) + default = {} +} + +################################################################################ +# Stage +################################################################################ + +variable "create_stage" { + description = "Whether to create default stage" + type = bool + default = true +} + +variable "stage_access_log_settings" { + description = "Settings for logging access in this stage. Use the aws_api_gateway_account resource to configure [permissions for CloudWatch Logging](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html#set-up-access-logging-permissions)" + type = object({ + create_log_group = optional(bool, true) + destination_arn = optional(string) + format = optional(string) + log_group_name = optional(string) + log_group_retention_in_days = optional(number, 30) + log_group_kms_key_id = optional(string) + log_group_skip_destroy = optional(bool) + log_group_class = optional(string) + log_group_tags = optional(map(string), {}) + }) + default = {} +} + +variable "stage_client_certificate_id" { + description = "The identifier of a client certificate for the stage. Use the `aws_api_gateway_client_certificate` resource to configure a client certificate. Supported only for WebSocket APIs" + type = string + default = null +} + +variable "stage_default_route_settings" { + description = "The default route settings for the stage" + type = object({ + data_trace_enabled = optional(bool, true) + detailed_metrics_enabled = optional(bool, true) + logging_level = optional(string) + throttling_burst_limit = optional(number, 500) + throttling_rate_limit = optional(number, 1000) + }) + default = {} +} + +variable "stage_description" { + description = "The description for the stage. Must be less than or equal to 1024 characters in length" + type = string + default = null +} + +variable "stage_name" { + description = "The name of the stage. Must be between 1 and 128 characters in length" + type = string + default = "$default" +} + +variable "stage_variables" { + description = "A map that defines the stage variables for the stage" + type = map(string) + default = {} +} + +variable "stage_tags" { + description = "A mapping of tags to assign to the stage resource" + type = map(string) + default = {} +} + +################################################################################ +# Deployment +################################################################################ + +variable "deploy_stage" { + description = "Whether to deploy the stage. `HTTP` APIs are auto-deployed by default" + type = bool + default = true +} + +################################################################################ +# VPC Link +################################################################################ + +variable "vpc_links" { + description = "Map of VPC Link definitions to create" + type = map(object({ + name = optional(string) + security_group_ids = optional(list(string)) + subnet_ids = optional(list(string)) + tags = optional(map(string), {}) + })) + default = {} +} + +variable "vpc_link_tags" { + description = "A map of tags to add to the VPC Links created" + type = map(string) + default = {} +} diff --git a/versions.tf b/versions.tf index 97e1864..623b21b 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ -terraform { - required_version = ">= 1.3" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.96" - } - } -} +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.96" + } + } +} diff --git a/wrappers/README.md b/wrappers/README.md index 40e4194..def247d 100644 --- a/wrappers/README.md +++ b/wrappers/README.md @@ -12,9 +12,9 @@ This wrapper does not implement any extra functionality. ```hcl terraform { - source = "tfr:///terraform-aws-modules/apigateway-v2/aws//wrappers" + source = "tfr:///terraform-aws-modules/aws-apigatewayv2/aws//wrappers" # Alternative source: - # source = "git::git@github.com:terraform-aws-modules/terraform-aws-apigateway-v2.git//wrappers?ref=master" + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-aws-apigatewayv2.git//wrappers?ref=master" } inputs = { @@ -42,7 +42,7 @@ inputs = { ```hcl module "wrapper" { - source = "terraform-aws-modules/apigateway-v2/aws//wrappers" + source = "terraform-aws-modules/aws-apigatewayv2/aws//wrappers" defaults = { # Default values create = true diff --git a/wrappers/main.tf b/wrappers/main.tf index 879333a..8deb054 100644 --- a/wrappers/main.tf +++ b/wrappers/main.tf @@ -27,6 +27,7 @@ module "wrapper" { ip_address_type = try(each.value.ip_address_type, var.defaults.ip_address_type, null) mutual_tls_authentication = try(each.value.mutual_tls_authentication, var.defaults.mutual_tls_authentication, {}) name = try(each.value.name, var.defaults.name, "") + private_zone = try(each.value.private_zone, var.defaults.private_zone, false) protocol_type = try(each.value.protocol_type, var.defaults.protocol_type, "HTTP") route_key = try(each.value.route_key, var.defaults.route_key, null) route_selection_expression = try(each.value.route_selection_expression, var.defaults.route_selection_expression, null) diff --git a/wrappers/versions.tf b/wrappers/versions.tf index 97e1864..623b21b 100644 --- a/wrappers/versions.tf +++ b/wrappers/versions.tf @@ -1,10 +1,10 @@ -terraform { - required_version = ">= 1.3" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.96" - } - } -} +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.96" + } + } +} From 830ab2b4febda99c19f514940474809e159ef6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Ruiz?= <50803935+agustin58ruiz@users.noreply.github.com> Date: Mon, 19 May 2025 09:39:13 -0300 Subject: [PATCH 4/4] Adding correccions from pre-commit action --- wrappers/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wrappers/README.md b/wrappers/README.md index def247d..40e4194 100644 --- a/wrappers/README.md +++ b/wrappers/README.md @@ -12,9 +12,9 @@ This wrapper does not implement any extra functionality. ```hcl terraform { - source = "tfr:///terraform-aws-modules/aws-apigatewayv2/aws//wrappers" + source = "tfr:///terraform-aws-modules/apigateway-v2/aws//wrappers" # Alternative source: - # source = "git::git@github.com:terraform-aws-modules/terraform-aws-aws-apigatewayv2.git//wrappers?ref=master" + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-apigateway-v2.git//wrappers?ref=master" } inputs = { @@ -42,7 +42,7 @@ inputs = { ```hcl module "wrapper" { - source = "terraform-aws-modules/aws-apigatewayv2/aws//wrappers" + source = "terraform-aws-modules/apigateway-v2/aws//wrappers" defaults = { # Default values create = true