From 1b8d208403ed666d6f84f707f394df7b5e9b595a Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Tue, 11 Jan 2022 13:37:48 -0500 Subject: [PATCH 1/2] Update for better Terraform 1.x support * Remove provider block from module * Remove aws.use1 provider reference on resources * Add terraform-null-label module for context support * Update input from `zone_ids` to `zones` * Use terraform-aws-kms-key module for KMS key creation * Use build-harness framework Signed-off-by: Jeremy T. Bouse --- .github/CODEOWNERS | 25 + .github/ISSUE_TEMPLATE/bug_report.md | 37 ++ .github/ISSUE_TEMPLATE/config.yml | 18 + .github/ISSUE_TEMPLATE/feature_request.md | 36 ++ .github/ISSUE_TEMPLATE/question.md | 0 .github/PULL_REQUEST_TEMPLATE.md | 13 + .github/auto-release.yml | 54 ++ .github/mergify.yml | 65 ++ .github/renovate.json | 12 + .github/workflows/auto-context.yml | 57 ++ .github/workflows/auto-format.yml | 88 +++ .github/workflows/auto-release.yml | 26 + .github/workflows/chatops.yml | 37 ++ .github/workflows/validate-codeowners.yml | 27 + LICENSE | 574 ++++++------------ Makefile | 10 + README.md | 352 +++++++++-- README.yaml | 94 +++ context.tf | 279 +++++++++ docs/targets.md | 12 + docs/terraform.md | 63 ++ examples/complete/context.tf | 279 +++++++++ examples/complete/main.tf | 0 examples/complete/outputs.tf | 0 provider.tf => examples/complete/providers.tf | 3 +- examples/complete/variables.tf | 0 examples/complete/versions.tf | 0 main.tf | 37 +- outputs.tf | 7 +- variables.tf | 18 +- 30 files changed, 1769 insertions(+), 454 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/auto-release.yml create mode 100644 .github/mergify.yml create mode 100644 .github/renovate.json create mode 100644 .github/workflows/auto-context.yml create mode 100644 .github/workflows/auto-format.yml create mode 100644 .github/workflows/auto-release.yml create mode 100644 .github/workflows/chatops.yml create mode 100644 .github/workflows/validate-codeowners.yml create mode 100644 Makefile create mode 100644 README.yaml create mode 100644 context.tf create mode 100644 docs/targets.md create mode 100644 docs/terraform.md create mode 100644 examples/complete/context.tf create mode 100644 examples/complete/main.tf create mode 100644 examples/complete/outputs.tf rename provider.tf => examples/complete/providers.tf (66%) create mode 100644 examples/complete/variables.tf create mode 100644 examples/complete/versions.tf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..9e0a825 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,25 @@ +# Use this file to define individuals or teams that are responsible for code in a repository. +# Read more: +# +# Order is important: the last matching pattern has the highest precedence + +# These owners will be the default owners for everything +* @ugns/engineering @ugns/contributors + +# Cloud Posse must review any changes to Makefiles +**/Makefile @ugns/engineering +**/Makefile.* @ugns/engineering + +# Cloud Posse must review any changes to GitHub actions +.github/* @ugns/engineering + +# Cloud Posse must review any changes to standard context definition, +# but some changes can be rubber-stamped. +**/*.tf @ugns/engineering @ugns/contributors @ugns/approvers +README.yaml @ugns/engineering @ugns/contributors @ugns/approvers +README.md @ugns/engineering @ugns/contributors @ugns/approvers +docs/*.md @ugns/engineering @ugns/contributors @ugns/approvers + +# Cloud Posse Admins must review all changes to CODEOWNERS or the mergify configuration +.github/mergify.yml @ugns/admins +.github/CODEOWNERS @ugns/admins diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..f3df96b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: 'bug' +assignees: '' + +--- + +Found a bug? Maybe our [Slack Community](https://slack.cloudposse.com) can help. + +[![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) + +## Describe the Bug +A clear and concise description of what the bug is. + +## Expected Behavior +A clear and concise description of what you expected to happen. + +## Steps to Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Run '....' +3. Enter '....' +4. See error + +## Screenshots +If applicable, add screenshots or logs to help explain your problem. + +## Environment (please complete the following information): + +Anything that will help us triage the bug will help. Here are some ideas: + - OS: [e.g. Linux, OSX, WSL, etc] + - Version [e.g. 10.15] + +## Additional Context +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..76ae6d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,18 @@ +blank_issues_enabled: false + +contact_links: + + - name: Community Slack Team + url: https://cloudposse.com/slack/ + about: |- + Please ask and answer questions here. + + - name: Office Hours + url: https://cloudposse.com/office-hours/ + about: |- + Join us every Wednesday for FREE Office Hours (lunch & learn). + + - name: DevOps Accelerator Program + url: https://cloudposse.com/accelerate/ + about: |- + Own your infrastructure in record time. We build it. You drive it. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..39a8686 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,36 @@ +--- +name: Feature Request +about: Suggest an idea for this project +title: '' +labels: 'feature request' +assignees: '' + +--- + +Have a question? Please checkout our [Slack Community](https://slack.cloudposse.com) or visit our [Slack Archive](https://archive.sweetops.com/). + +[![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) + +## Describe the Feature + +A clear and concise description of what the bug is. + +## Expected Behavior + +A clear and concise description of what you expected to happen. + +## Use Case + +Is your feature request related to a problem/challenge you are trying to solve? Please provide some additional context of why this feature or capability will be valuable. + +## Describe Ideal Solution + +A clear and concise description of what you want to happen. If you don't know, that's okay. + +## Alternatives Considered + +Explain what alternative solutions or features you've considered. + +## Additional Context + +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..e69de29 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4b8f32d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +## what +* Describe high-level what changed as a result of these commits (i.e. in plain-english, what do these changes mean?) +* Use bullet points to be concise and to the point. + +## why +* Provide the justifications for the changes (e.g. business case). +* Describe why these changes were made (e.g. why do these commits fix the problem?) +* Use bullet points to be concise and to the point. + +## references +* Link to any supporting github issues or helpful documentation to add some context (e.g. stackoverflow). +* Use `closes #123`, if this PR closes a GitHub issue `#123` + diff --git a/.github/auto-release.yml b/.github/auto-release.yml new file mode 100644 index 0000000..b45efb7 --- /dev/null +++ b/.github/auto-release.yml @@ -0,0 +1,54 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: '$RESOLVED_VERSION' +version-template: '$MAJOR.$MINOR.$PATCH' +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + - 'enhancement' + patch: + labels: + - 'auto-update' + - 'patch' + - 'fix' + - 'bugfix' + - 'bug' + - 'hotfix' + - 'no-release' + default: 'minor' + +categories: +- title: '🚀 Enhancements' + labels: + - 'enhancement' + - 'patch' +- title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - 'hotfix' +- title: '🤖 Automatic Updates' + labels: + - 'auto-update' + +change-template: | +
+ $TITLE @$AUTHOR (#$NUMBER) + + $BODY +
+ +template: | + $CHANGES + +replacers: +# Remove irrelevant information from Renovate bot +- search: '/(?<=---\s)\s*^#.*(Renovate configuration|Configuration)(?:.|\n)*?This PR has been generated .*/gm' + replace: '' +# Remove Renovate bot banner image +- search: '/\[!\[[^\]]*Renovate\][^\]]*\](\([^)]*\))?\s*\n+/gm' + replace: '' diff --git a/.github/mergify.yml b/.github/mergify.yml new file mode 100644 index 0000000..7e9a71d --- /dev/null +++ b/.github/mergify.yml @@ -0,0 +1,65 @@ +# https://docs.mergify.io/conditions.html +# https://docs.mergify.io/actions.html +pull_request_rules: +- name: "approve automated PRs that have passed checks" + conditions: + - "author~=^(undergridbot|renovate\\[bot\\])$" + - "base=master" + - "-closed" + - "head~=^(auto-update|renovate)/.*" + - "check-success=test/bats" + - "check-success=test/readme" + - "check-success=test/terratest" + - "check-success=validate-codeowners" + actions: + review: + type: "APPROVE" + bot_account: "undergrid-mergebot" + message: "We've automatically approved this PR because the checks from the automated Pull Request have passed." + +- name: "merge automated PRs when approved and tests pass" + conditions: + - "author~=^(undergridbot|renovate\\[bot\\])$" + - "base=master" + - "-closed" + - "head~=^(auto-update|renovate)/.*" + - "check-success=test/bats" + - "check-success=test/readme" + - "check-success=test/terratest" + - "check-success=validate-codeowners" + - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" + - "#commented-reviews-by=0" + actions: + merge: + method: "squash" + +- name: "delete the head branch after merge" + conditions: + - "merged" + actions: + delete_head_branch: {} + +- name: "ask to resolve conflict" + conditions: + - "conflict" + - "-closed" + actions: + comment: + message: "This pull request is now in conflict. Could you fix it @{{author}}? 🙏" + +- name: "remove outdated reviews" + conditions: + - "base=master" + actions: + dismiss_reviews: + changes_requested: true + approved: true + message: "This Pull Request has been updated, so we're dismissing all reviews." + +- name: "close Pull Requests without files changed" + conditions: + - "#files=0" + actions: + close: + message: "This pull request has been automatically closed by Mergify because there are no longer any changes." diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..ae4f0aa --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,12 @@ +{ + "extends": [ + "config:base", + ":preserveSemverRanges" + ], + "labels": ["auto-update"], + "enabledManagers": ["terraform"], + "terraform": { + "ignorePaths": ["**/context.tf", "examples/**"] + } +} + diff --git a/.github/workflows/auto-context.yml b/.github/workflows/auto-context.yml new file mode 100644 index 0000000..f8a59cf --- /dev/null +++ b/.github/workflows/auto-context.yml @@ -0,0 +1,57 @@ +name: "auto-context" +on: + schedule: + # Update context.tf nightly + - cron: '0 3 * * *' + +jobs: + update: + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Update context.tf + shell: bash + id: update + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + run: | + if [[ -f context.tf ]]; then + echo "Discovered existing context.tf! Fetching most recent version to see if there is an update." + curl -o context.tf -fsSL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf + if git diff --no-patch --exit-code context.tf; then + echo "No changes detected! Exiting the job..." + else + echo "context.tf file has changed. Update examples and rebuild README.md." + make init + make github/init/context.tf + make readme/build + echo "::set-output name=create_pull_request::true" + fi + else + echo "This module has not yet been updated to support the context.tf pattern! Please update in order to support automatic updates." + fi + + - name: Create Pull Request + if: steps.update.outputs.create_pull_request == 'true' + uses: ugns/actions/github/create-pull-request@1.0.0 + with: + token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + committer: 'undergridbot <97003863+undergridbot@users.noreply.github.com>' + author: 'undergridbot <97003863+undergridbot@users.noreply.github.com>' + commit-message: Update context.tf from origin source + title: Update context.tf + body: |- + ## what + This is an auto-generated PR that updates the `context.tf` file to the latest version from `cloudposse/terraform-null-label` + + ## why + To support all the features of the `context` interface. + + branch: auto-update/context.tf + base: master + delete-branch: true + labels: | + auto-update + context diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml new file mode 100644 index 0000000..5d1830a --- /dev/null +++ b/.github/workflows/auto-format.yml @@ -0,0 +1,88 @@ +name: Auto Format +on: + pull_request_target: + types: [opened, synchronize] + +jobs: + auto-format: + runs-on: ubuntu-latest + container: ugns/build-harness:latest + steps: + # Checkout the pull request branch + # "An action in a workflow run can’t trigger a new workflow run. For example, if an action pushes code using + # the repository’s GITHUB_TOKEN, a new workflow will not run even when the repository contains + # a workflow configured to run when push events occur." + # However, using a personal access token will cause events to be triggered. + # We need that to ensure a status gets posted after the auto-format commit. + # We also want to trigger tests if the auto-format made no changes. + - uses: actions/checkout@v2 + if: github.event.pull_request.state == 'open' + name: Privileged Checkout + with: + token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + # Check out the PR commit, not the merge commit + # Use `ref` instead of `sha` to enable pushing back to `ref` + ref: ${{ github.event.pull_request.head.ref }} + + # Do all the formatting stuff + - name: Auto Format + if: github.event.pull_request.state == 'open' + shell: bash + env: + GITHUB_TOKEN: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" + run: make BUILD_HARNESS_PATH=/build-harness PACKAGES_PREFER_HOST=true -f /build-harness/templates/Makefile.build-harness pr/auto-format/host + + # Commit changes (if any) to the PR branch + - name: Commit changes to the PR branch + if: github.event.pull_request.state == 'open' + shell: bash + id: commit + env: + SENDER: ${{ github.event.sender.login }} + run: | + set -x + output=$(git diff --name-only) + + if [ -n "$output" ]; then + echo "Changes detected. Pushing to the PR branch" + git config --global user.name 'undergridbot' + git config --global user.email '97003863+undergridbot@users.noreply.github.com' + git add -A + git commit -m "Auto Format" + # Prevent looping by not pushing changes in response to changes from undergridbot + [[ $SENDER == "undergridbot" ]] || git push + # Set status to fail, because the push should trigger another status check, + # and we use success to indicate the checks are finished. + printf "::set-output name=%s::%s\n" "changed" "true" + exit 1 + else + printf "::set-output name=%s::%s\n" "changed" "false" + echo "No changes detected" + fi + + - name: Auto Test + uses: ugns/actions/github/repository-dispatch@1.0.0 + # match users by ID because logins (user names) are inconsistent, + # for example in the REST API Renovate Bot is `renovate[bot]` but + # in GraphQL it is just `renovate`, plus there is a non-bot + # user `renovate` with ID 1832810. + # Mergify bot: 37929162 + # Renovate bot: 29139614 + # UnderGrid bot: 97003863 + # Need to use space separators to prevent "21" from matching "112144" + if: > + contains(' 37929162 29139614 97003863', format(' {0} ', github.event.pull_request.user.id)) + && steps.commit.outputs.changed == 'false' && github.event.pull_request.state == 'open' + with: + token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + repository: ugns/actions + event-type: test-command + client-payload: |- + { "slash_command":{"args": {"unnamed": {"all": "all", "arg1": "all"}}}, + "pull_request": ${{ toJSON(github.event.pull_request) }}, + "github":{"payload":{"repository": ${{ toJSON(github.event.repository) }}, + "comment": {"id": ""} + } + } + } diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml new file mode 100644 index 0000000..3a38fae --- /dev/null +++ b/.github/workflows/auto-release.yml @@ -0,0 +1,26 @@ +name: auto-release + +on: + push: + branches: + - main + - master + - production + +jobs: + publish: + runs-on: ubuntu-latest + steps: + # Get PR from merged commit to master + - uses: actions-ecosystem/action-get-merged-pull-request@v1 + id: get-merged-pull-request + with: + github_token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + # Drafts your next Release notes as Pull Requests are merged into "main" + - uses: release-drafter/release-drafter@v5 + with: + publish: ${{ !contains(steps.get-merged-pull-request.outputs.labels, 'no-release') }} + prerelease: false + config-name: auto-release.yml + env: + GITHUB_TOKEN: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} diff --git a/.github/workflows/chatops.yml b/.github/workflows/chatops.yml new file mode 100644 index 0000000..2d98a38 --- /dev/null +++ b/.github/workflows/chatops.yml @@ -0,0 +1,37 @@ +name: chatops +on: + issue_comment: + types: [created] + +jobs: + default: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: "Handle common commands" + uses: ugns/actions/github/slash-command-dispatch@1.0.0 + with: + token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + reaction-token: ${{ secrets.GITHUB_TOKEN }} + repository: ugns/actions + commands: rebuild-readme, terraform-fmt + permission: triage + issue-type: pull-request + + test: + runs-on: ubuntu-latest + steps: + - name: "Checkout commit" + uses: actions/checkout@v2 + - name: "Run tests" + uses: ugns/actions/github/slash-command-dispatch@1.0.0 + with: + token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + reaction-token: ${{ secrets.GITHUB_TOKEN }} + repository: ugns/actions + commands: test + permission: triage + issue-type: pull-request + reactions: false + + diff --git a/.github/workflows/validate-codeowners.yml b/.github/workflows/validate-codeowners.yml new file mode 100644 index 0000000..c5193b6 --- /dev/null +++ b/.github/workflows/validate-codeowners.yml @@ -0,0 +1,27 @@ +name: Validate Codeowners +on: + workflow_dispatch: + + pull_request: + +jobs: + validate-codeowners: + runs-on: ubuntu-latest + steps: + - name: "Checkout source code at current commit" + uses: actions/checkout@v2 + - uses: mszostok/codeowners-validator@v0.5.0 + if: github.event.pull_request.head.repo.full_name == github.repository + name: "Full check of CODEOWNERS" + with: + # For now, remove "files" check to allow CODEOWNERS to specify non-existent + # files so we can use the same CODEOWNERS file for Terraform and non-Terraform repos + # checks: "files,syntax,owners,duppatterns" + checks: "syntax,owners,duppatterns" + # GitHub access token is required only if the `owners` check is enabled + github_access_token: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" + - uses: mszostok/codeowners-validator@v0.5.0 + if: github.event.pull_request.head.repo.full_name != github.repository + name: "Syntax check of CODEOWNERS" + with: + checks: "syntax,duppatterns" diff --git a/LICENSE b/LICENSE index a612ad9..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,373 +1,201 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bf0523a --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +SHELL := /bin/bash + +# List of targets the `readme` target should call before generating the readme +export README_DEPS ?= docs/targets.md docs/terraform.md + +-include $(shell curl -sSL -o .build-harness "https://git.io/undergrid-build-harness"; echo .build-harness) + +## Lint terraform code +lint: + $(SELF) terraform/install terraform/get-modules terraform/lint terraform/validate diff --git a/README.md b/README.md index 178a524..f35fdea 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,348 @@ -# AWS Route53 DNSSEC Terraform Module -Terraform module which creates an AWS Key Management Service (KMS) Customer -Managed Key (CMK) for Route53 DNS to use as a Key-signing Key (KSK) for -enabling DNSSEC on a Hosted Zone. + +# terraform-aws-route53-dnssec [![Latest Release](https://img.shields.io/github/release/ugns/terraform-aws-route53-dnssec.svg)](https://github.com/ugns/terraform-aws-route53-dnssec/releases/latest) + -KSK is setup using a random string and CMK sets up using a name prefix of -'alias/ksk-'. CMK has an AWS recommended IAM key policy applied to it and -is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required. +[![UnderGrid Network Services][logo]](https://undergrid.net) -## Terraform versions + + +Short +description + +--- + +This project is part of our comprehensive approach towards DevOps. +[][share_email] +[][share_googleplus] +[][share_facebook] +[][share_reddit] +[][share_linkedin] +[][share_twitter] + +Designed following the [Cloud Posse, LLC][cloudposse] ["SweetOps"][sweetops] approach. + + +[![Terraform Open Source Modules](https://docs.cloudposse.com/images/terraform-open-source-modules.svg)][terraform_modules] + + + +It's 100% Open Source and licensed under the [APACHE2](LICENSE). + + + + + + + +We literally have [*hundreds of terraform modules*][terraform_modules] that are Open Source and well-maintained. Check them out! + + + + + +## Introduction + +This is an introduction. + + +## Security & Compliance [](https://bridgecrew.io/) + +Security scanning provided by Bridgecrew. Bridgecrew is the leading fully hosted, cloud-native solution providing continuous Terraform security and compliance. + +| Benchmark | Description | +|--------|---------------| +| [![Infrastructure Security](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/general)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=INFRASTRUCTURE+SECURITY) | Infrastructure Security Compliance | +| [![CIS KUBERNETES](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/cis_kubernetes)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=CIS+KUBERNETES+V1.5) | Center for Internet Security, KUBERNETES Compliance | +| [![CIS AWS](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/cis_aws)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=CIS+AWS+V1.2) | Center for Internet Security, AWS Compliance | +| [![CIS AZURE](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/cis_azure)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=CIS+AZURE+V1.1) | Center for Internet Security, AZURE Compliance | +| [![PCI-DSS](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/pci)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=PCI-DSS+V3.2) | Payment Card Industry Data Security Standards Compliance | +| [![NIST-800-53](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/nist)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=NIST-800-53) | National Institute of Standards and Technology Compliance | +| [![ISO27001](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/iso)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=ISO27001) | Information Security Management System, ISO/IEC 27001 Compliance | +| [![SOC2](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/soc2)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=SOC2)| Service Organization Control 2 Compliance | +| [![CIS GCP](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/cis_gcp)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=CIS+GCP+V1.1) | Center for Internet Security, GCP Compliance | +| [![HIPAA](https://www.bridgecrew.cloud/badges/github/ugns/terraform-aws-route53-dnssec/hipaa)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=ugns%2Fterraform-aws-route53-dnssec&benchmark=HIPAA) | Health Insurance Portability and Accountability Compliance | + + + +## Usage + + +**IMPORTANT:** We do not pin modules to versions in our examples because of the +difficulty of keeping the versions in the documentation in sync with the latest released versions. +We highly recommend that in your code you pin the version to the exact version you are +using so that your infrastructure remains stable, and update versions in a +systematic way so that they do not catch you by surprise. + +Also, because of a bug in the Terraform registry ([hashicorp/terraform#21417](https://github.com/hashicorp/terraform/issues/21417)), +the registry shows many of our inputs as required when in fact they are optional. +The table below correctly indicates which inputs are required. + + +For a complete example, see [examples/complete](examples/complete). + +For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) +(which tests and deploys the example on AWS), see [test](test). ```hcl -module "ksk" { - source = "UGNS/route53-dnssec/aws" +# Create a standard label resource. See [null-label](https://github.com/cloudposse/terraform-null-label/#terraform-null-label--) +module "label" { + source = "cloudposse/label/null" + # Cloud Posse recommends pinning every module to a specific version, though usually you want to use the current one + # version = "x.x.x" + + namespace = "eg" + name = "example" +} - # ... omitted +module "example" { + source = "cloudposse/*****/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + + example = "Hello world!" + + context = module.label.this } ``` -## Notes +## Quick Start + +Here's how to get started... + + +## Examples + +Here is an example of using this module: +- [`examples/complete`](https://github.com/ugns/terraform-aws-route53-dnssec/tree/main/examples/complete) - complete example of using this module + -Manual steps will still need to be taken to actually enable DNSSEC for the Route53 -Hosted Zone. -* Establish a chain of trust with domain registrar -* Enable DNSSEC signing with the KSK + +## Makefile Targets +```text +Available targets: -These steps can not be automated at this time and thus require manual effort to -complete the process. Until both steps are taken DNSSEC will not be protecting -your zone records. + help Help screen + help/all Display help for all targets + help/short This help short screen + lint Lint terraform code +``` + + ## Requirements | Name | Version | |------|---------| -| terraform | >= 0.13 | -| aws | ~> 3.0 | -| random | ~> 3.0 | +| [terraform](#requirement\_terraform) | >= 0.13 | +| [aws](#requirement\_aws) | ~> 3.0 | +| [random](#requirement\_random) | ~> 3.0 | ## Providers | Name | Version | |------|---------| -| aws | ~> 3.0 | -| random | ~> 3.0 | +| [aws](#provider\_aws) | 3.71.0 | +| [random](#provider\_random) | 3.1.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [this](#module\_this) | cloudposse/label/null | 0.25.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | +| [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.ksk](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| tags | A mapping of tags to assign to the resource | `map(string)` | `{}` | no | -| zone\_ids | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | +| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | +| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | +| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | +| [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | +| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | ## Outputs | Name | Description | |------|-------------| -| this_key_arn | KMS key ARN for Route53 DNSSEC CMK | +| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | + + + + +## Share the Love + +Like this project? Please give it a ★ on [our GitHub](https://github.com/ugns/terraform-aws-route53-dnssec)! (it helps us **a lot**) + + + +## Related Projects + +Check out these related projects. + +- [terraform-null-label](https://github.com/cloudposse/terraform-null-label) - Terraform module designed to generate consistent names and tags for resources. Use terraform-null-label to implement a strict naming convention. + + +## References + +For additional context, refer to some of these links. + + + +## Help + +**Got a question?** We got answers. + +File a GitHub [issue](https://github.com/ugns/terraform-aws-route53-dnssec/issues). + +## Contributing + +### Bug Reports & Feature Requests + +Please use the [issue tracker](https://github.com/ugns/terraform-aws-route53-dnssec/issues) to report any bugs or file feature requests. + +### Developing + +If you are interested in being a contributor and want to get involved in developing this project or help out with our other projects, we would love to hear from you!. + +In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. + + 1. **Fork** the repo on GitHub + 2. **Clone** the project to your own machine + 3. **Commit** changes to your own branch + 4. **Push** your work back up to your fork + 5. Submit a **Pull Request** so that we can review your changes + +**NOTE:** Be sure to merge the latest changes from "upstream" before making a pull request! + + + +## Copyrights + +Copyright © 2021-2022 [UnderGrid Network Services](https://undergrid.net) + + -## Authors -Module managed by [Jeremy T. Bouse](https://github.com/jbouse) for [UnderGrid Network Services](https://github.com/UGNS). ## License -Mozilla Public License 2.0. See LICENSE for fulld details. +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +See [LICENSE](LICENSE) for full details. + +```text +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +``` + + + + + + + + + +## Trademarks + +All other trademarks referenced herein are the property of their respective owners. + +## About + +This project is maintained and funded by [UnderGrid Network Services][website]. Like it? Please let us know! + +[![UnderGrid Network Services][logo]][website] + +We're a DevOps Professional Services consulting firm based in Kissimmee, FL. + +Check out [our other projects][github]. + + +### Contributors + + +| [![Jeremy T. Bouse][jbouse_avatar]][jbouse_homepage]
[Jeremy T. Bouse][jbouse_homepage] | +|---| + + + [jbouse_homepage]: https://github.com/jbouse + [jbouse_avatar]: https://img.cloudposse.com/150x150/https://github.com/jbouse.png + +[![Beacon][beacon]][website] + + [logo]: https://undergrid.net/undergrid-logo-300x88.png + [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=docs + [website]: https://undergrid.net?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=website + [cloudposse]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=cloudposse + [sweetops]: https://cpco.io/sweetops?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=sweetops + [github]: https://github.com/ugns?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=github + [linkedin]: https://www.linkedin.com/company/undergrid-network-services/?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=linkedin + [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=email + [terraform_modules]: https://github.com/ugns?utm_source=github&utm_medium=readme&utm_campaign=ugns/terraform-aws-route53-dnssec&utm_content=terraform_modules + [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-aws-route53-dnssec&url=https://github.com/ugns/terraform-aws-route53-dnssec + [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-aws-route53-dnssec&url=https://github.com/ugns/terraform-aws-route53-dnssec + [share_reddit]: https://reddit.com/submit/?url=https://github.com/ugns/terraform-aws-route53-dnssec + [share_facebook]: https://facebook.com/sharer/sharer.php?u=https://github.com/ugns/terraform-aws-route53-dnssec + [share_googleplus]: https://plus.google.com/share?url=https://github.com/ugns/terraform-aws-route53-dnssec + [share_email]: mailto:?subject=terraform-aws-route53-dnssec&body=https://github.com/ugns/terraform-aws-route53-dnssec + [beacon]: https://ga-beacon.cloudposse.com/UA-2819624-1/ugns/terraform-aws-route53-dnssec?pixel&cs=github&cm=readme&an=terraform-aws-route53-dnssec diff --git a/README.yaml b/README.yaml new file mode 100644 index 0000000..9505be3 --- /dev/null +++ b/README.yaml @@ -0,0 +1,94 @@ +# +# This is the canonical configuration for the `README.md` +# Run `make readme` to rebuild the `README.md` +# + +# Name of this project +name: "terraform-aws-route53-dnssec" + +# Logo for this project +#logo: docs/logo.png + +# License of this project +license: "APACHE2" + +# Copyrights +copyrights: +- name: "UnderGrid Network Services" + url: "https://undergrid.net" + year: "2021" + +# Canonical GitHub repo +github_repo: "ugns/terraform-aws-route53-dnssec" + +# Badges to display +badges: +- name: "Latest Release" + image: "https://img.shields.io/github/release/ugns/terraform-aws-route53-dnssec.svg" + url: "https://github.com/ugns/terraform-aws-route53-dnssec/releases/latest" + +# List any related terraform modules that this module may be used with or that this module depends on. +related: +- name: "terraform-null-label" + description: "Terraform module designed to generate consistent names and tags for resources. Use terraform-null-label to implement a strict naming convention." + url: "https://github.com/cloudposse/terraform-null-label" + +# List any resources helpful for someone to get started. For example, link to the hashicorp documentation or AWS documentation. +references: + +# Short description of this project +description: |- + Short + description + +# Introduction to the project +introduction: |- + This is an introduction. + +# How to use this module. Should be an easy example to copy and paste. +usage: |- + For a complete example, see [examples/complete](examples/complete). + + For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) + (which tests and deploys the example on AWS), see [test](test). + + ```hcl + # Create a standard label resource. See [null-label](https://github.com/cloudposse/terraform-null-label/#terraform-null-label--) + module "label" { + source = "cloudposse/label/null" + # Cloud Posse recommends pinning every module to a specific version, though usually you want to use the current one + # version = "x.x.x" + + namespace = "eg" + name = "example" + } + + module "example" { + source = "cloudposse/*****/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + + example = "Hello world!" + + context = module.label.this + } + ``` + +# Example usage +examples: |- + Here is an example of using this module: + - [`examples/complete`](https://github.com/ugns/terraform-aws-route53-dnssec/tree/main/examples/complete) - complete example of using this module + +# How to get started quickly +quickstart: |- + Here's how to get started... + +# Other files to include in this README from the project folder +include: +- "docs/targets.md" +- "docs/terraform.md" + +# Contributors to this project +contributors: +- name: "Jeremy T. Bouse" + github: "jbouse" diff --git a/context.tf b/context.tf new file mode 100644 index 0000000..5e0ef88 --- /dev/null +++ b/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/docs/targets.md b/docs/targets.md new file mode 100644 index 0000000..3dce8b3 --- /dev/null +++ b/docs/targets.md @@ -0,0 +1,12 @@ + +## Makefile Targets +```text +Available targets: + + help Help screen + help/all Display help for all targets + help/short This help short screen + lint Lint terraform code + +``` + diff --git a/docs/terraform.md b/docs/terraform.md new file mode 100644 index 0000000..618b514 --- /dev/null +++ b/docs/terraform.md @@ -0,0 +1,63 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13 | +| [aws](#requirement\_aws) | ~> 3.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 3.71.0 | +| [random](#provider\_random) | 3.1.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [this](#module\_this) | cloudposse/label/null | 0.25.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | +| [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.ksk](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | +| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | +| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | +| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | +| [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | +| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | + diff --git a/examples/complete/context.tf b/examples/complete/context.tf new file mode 100644 index 0000000..5e0ef88 --- /dev/null +++ b/examples/complete/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/examples/complete/main.tf b/examples/complete/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/provider.tf b/examples/complete/providers.tf similarity index 66% rename from provider.tf rename to examples/complete/providers.tf index 0fcba4b..e70fb2f 100644 --- a/provider.tf +++ b/examples/complete/providers.tf @@ -1,4 +1,3 @@ provider "aws" { - alias = "use1" region = "us-east-1" -} +} \ No newline at end of file diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf new file mode 100644 index 0000000..e69de29 diff --git a/main.tf b/main.tf index 5f47f13..c29efc3 100644 --- a/main.tf +++ b/main.tf @@ -1,31 +1,22 @@ -resource "aws_kms_key" "this" { - provider = aws.use1 - customer_master_key_spec = "ECC_NIST_P256" - key_usage = "SIGN_VERIFY" - deletion_window_in_days = 7 +module "kms_key" { + source = "cloudposse/kms-key/aws" + version = "0.12.1" description = "Route53 DNSSEC customer managed CMK" + deletion_window_in_days = var.deletion_window_in_days + enable_key_rotation = false + key_usage = "SIGN_VERIFY" + customer_master_key_spec = "ECC_NIST_P256" policy = data.aws_iam_policy_document.ksk.json - tags = merge( - var.tags, - { - ManagedBy = "Terraform" - Changed = formatdate("YYYY-MM-DD hh:mm ZZZ", timestamp()) - }, - ) -} - -resource "aws_kms_alias" "this" { - provider = aws.use1 - name_prefix = "alias/ksk-" - target_key_id = aws_kms_key.this.key_id + context = module.this.context + attributes = ["ksk"] } resource "random_string" "ksk" { - for_each = toset(var.zone_ids) + for_each = local.zones keepers = { - hosted_zone_id = each.key - key_management_service_arn = aws_kms_key.this.arn + hosted_zone_id = each.value.zone_id + key_management_service_arn = module.kms_key.key_arn } length = 32 @@ -33,9 +24,9 @@ resource "random_string" "ksk" { } resource "aws_route53_key_signing_key" "this" { - for_each = toset(var.zone_ids) + for_each = local.zones hosted_zone_id = random_string.ksk[each.key].keepers.hosted_zone_id - key_management_service_arn = aws_kms_key.this.arn + key_management_service_arn = module.kms_key.key_arn name = random_string.ksk[each.key].id } diff --git a/outputs.tf b/outputs.tf index b00ec30..4342bc2 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,4 +1,9 @@ output "this_key_arn" { + description = "Deprecated: KMS key arn for Route53 DNSSEC CMK" + value = module.kms_key.key_arn +} + +output "key_arn" { description = "KMS key arn for Route53 DNSSEC CMK" - value = aws_kms_key.this.arn + value = module.kms_key.key_arn } diff --git a/variables.tf b/variables.tf index 1eb3f6c..7e4a233 100644 --- a/variables.tf +++ b/variables.tf @@ -1,11 +1,15 @@ -variable "tags" { - type = map(string) - description = "A mapping of tags to assign to the resource" +variable "zones" { + description = "A list of Hosted Zone IDs to assign KSK to" + type = map(map(string)) default = {} } -variable "zone_ids" { - description = "A list of Hosted Zone IDs to assign KSK to" - type = list(string) - default = [] +variable "deletion_window_in_days" { + type = number + description = "(optional) describe your variable" + default = 7 +} + +locals { + zones = module.this.enabled ? var.zones : {} } \ No newline at end of file From 2b9f7e80bff000aaed572d20a7861494476c579c Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Tue, 11 Jan 2022 23:11:46 -0500 Subject: [PATCH 2/2] Update documentation Signed-off-by: Jeremy T. Bouse --- MIGRATION.md | 45 +++++++++++++++++++ README.md | 47 ++++++++++++++----- README.yaml | 50 +++++++++++++++------ docs/terraform.md | 9 ++-- examples/complete/fixtures.us-west-1.tfvars | 7 +++ examples/complete/main.tf | 12 +++++ examples/complete/outputs.tf | 4 ++ examples/complete/providers.tf | 7 ++- examples/complete/variables.tf | 4 ++ examples/complete/versions.tf | 11 +++++ variables.tf | 21 ++++++++- 11 files changed, 185 insertions(+), 32 deletions(-) create mode 100644 MIGRATION.md create mode 100644 examples/complete/fixtures.us-west-1.tfvars diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..ce1a5e0 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,45 @@ +# Migration to v1.0.0 + +## New Features + +With v1.0.0 we have tried to follow a more consistent pattern in +module design. + +- Use of the `context` provided by the [terraform-null-label](https://github.com/cloudposse/terraform-null-label) module. +- Ability to process hosted zones from other modules easier. + +## Breaking changes in v1.0.0 + +Releases prior to v1.0.0 of this module attempted to maintain compatibility, so required no code changes were needed. +With v1.0.0 in order to address reported issues changes to the code +were necessary that did not allow for upgrade without code changes. If you are unable to afford a break in functionality during upgrade lock +version to an earlier compatible version. + +### Behavior changes + +- Previously, the `aws_route53_key_signing_key` and `random_string` +resources used an index based on the hosted zone ID as passed in by the `zone_ids` variable. This caused an issue where the values were +not known until apply affecting plan execution. + +- Previously, the `aws_kms_key` and `ams_key_alias` resources were +handled internally. These are now handled with an external module +which will destroy the old resources upon apply. + +- Previously, prior to Terraform 1.0 `provider` blocks were necessary +inside external modules when requiring change from root module values. This causes issues when executing with newer versions. + +### Input Variable Changes + +- `zone_ids` removed. Use `zones` instead. + +- `zones` added. Internal changes required a new format for input +of zones to assign the KSK to. + +- `deletion_window_in_days` added. To change the deletion window on +key from the previous hard-coded default of 7 days. + +### Output Variable Changes + +- `this_key_arn` deprecated. Use `key_arn` instead. + +- `key_arm` added. Supplies the KMS key ARN setup for Route53 hosted zone KSK. \ No newline at end of file diff --git a/README.md b/README.md index f35fdea..633e58c 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,17 @@ --> -Short -description +Terraform module to provision an AWS Key Management Service (KMS) Customer Managed Key (CMK) +for Route53 DNS to use as a Key-signing Key (KSK) for enabling DNSSEC on a Hosted Zone. + +Provides the ability to instantiate a single KMS key to be used for multiple hosted zones. + +The KSK is setup using a random string. The CMK has an AWS recommended IAM key policy applied +to it and is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required. + +**IMPORTANT:** Route53 requires the KMS key be provisioned in the `us-east-1` region. If including +within a root module configured in another region then a provider alias must be passwd when using this +module. --- @@ -62,7 +71,7 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are ## Introduction -This is an introduction. + ## Security & Compliance [](https://bridgecrew.io/) @@ -98,9 +107,18 @@ the registry shows many of our inputs as required when in fact they are optional The table below correctly indicates which inputs are required. + +### Major Changes (breaking and otherwise) + +With the v1.0.0 release of this module, it has undergone major breaking changes and added +new functionality. Efforts were made to not create these breaking changes but they were +unavailable due to the nature of the issues fixed. Please see the [migration](MIGRATION.md) +document for details. + For a complete example, see [examples/complete](examples/complete). -For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) +For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) +and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). ```hcl @@ -115,19 +133,21 @@ module "label" { } module "example" { - source = "cloudposse/*****/aws" + source = "ugns/route53-dnssec/aws" # Cloud Posse recommends pinning every module to a specific version # version = "x.x.x" - example = "Hello world!" + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } context = module.label.this } ``` -## Quick Start -Here's how to get started... ## Examples @@ -169,14 +189,13 @@ Available targets: | Name | Source | Version | |------|--------|---------| +| [kms\_key](#module\_kms\_key) | cloudposse/kms-key/aws | 0.12.1 | | [this](#module\_this) | cloudposse/label/null | 0.25.0 | ## Resources | Name | Type | |------|------| -| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | | [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -189,6 +208,7 @@ Available targets: | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) The waiting period, specified in number of days.
After the waiting period ends, AWS KMS deletes the KMS key.
If you specify a value, it must be between 7 and 30, inclusive.
Defaults to `7`. | `number` | `7` | no | | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | @@ -204,13 +224,14 @@ Available targets: | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | -| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | +| [zones](#input\_zones) | (Optional) A map of hosted zones with `zone_id` to assign the
KSK to in the format of:
{
"example.com" = {
zone_id = "Z8VLZEXAMPLE"
}
}
Defaults to `{}` which will generate the KMS key and alias but
not assign it to a hosted zone which can be useful for staging. | `map(map(string))` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [key\_arn](#output\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [this\_key\_arn](#output\_this\_key\_arn) | Deprecated: KMS key arn for Route53 DNSSEC CMK | @@ -232,6 +253,8 @@ Check out these related projects. For additional context, refer to some of these links. +- [domain-configure-dnssec](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-configure-dnssec.html) - AWS Route53 Developers Guide: Configuring DNSSEC for a domain +- [dns-configuring-dnssec](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html) - AWS Route53 Developers Guide: Configuring DNSSEC signing in Amazone Route 53 ## Help diff --git a/README.yaml b/README.yaml index 9505be3..33ed47c 100644 --- a/README.yaml +++ b/README.yaml @@ -6,9 +6,6 @@ # Name of this project name: "terraform-aws-route53-dnssec" -# Logo for this project -#logo: docs/logo.png - # License of this project license: "APACHE2" @@ -35,21 +32,44 @@ related: # List any resources helpful for someone to get started. For example, link to the hashicorp documentation or AWS documentation. references: +- name: "domain-configure-dnssec" + description: "AWS Route53 Developers Guide: Configuring DNSSEC for a domain" + url: "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-configure-dnssec.html" +- name: "dns-configuring-dnssec" + description: "AWS Route53 Developers Guide: Configuring DNSSEC signing in Amazone Route 53" + url: "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html" # Short description of this project description: |- - Short - description + Terraform module to provision an AWS Key Management Service (KMS) Customer Managed Key (CMK) + for Route53 DNS to use as a Key-signing Key (KSK) for enabling DNSSEC on a Hosted Zone. + + Provides the ability to instantiate a single KMS key to be used for multiple hosted zones. + + The KSK is setup using a random string. The CMK has an AWS recommended IAM key policy applied + to it and is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required. + + **IMPORTANT:** Route53 requires the KMS key be provisioned in the `us-east-1` region. If including + within a root module configured in another region then a provider alias must be passwd when using this + module. # Introduction to the project -introduction: |- - This is an introduction. +introduction: "" # How to use this module. Should be an easy example to copy and paste. usage: |- + + ### Major Changes (breaking and otherwise) + + With the v1.0.0 release of this module, it has undergone major breaking changes and added + new functionality. Efforts were made to not create these breaking changes but they were + unavailable due to the nature of the issues fixed. Please see the [migration](MIGRATION.md) + document for details. + For a complete example, see [examples/complete](examples/complete). - For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) + For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) + and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). ```hcl @@ -64,12 +84,16 @@ usage: |- } module "example" { - source = "cloudposse/*****/aws" + source = "ugns/route53-dnssec/aws" # Cloud Posse recommends pinning every module to a specific version # version = "x.x.x" - example = "Hello world!" - + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + context = module.label.this } ``` @@ -80,8 +104,8 @@ examples: |- - [`examples/complete`](https://github.com/ugns/terraform-aws-route53-dnssec/tree/main/examples/complete) - complete example of using this module # How to get started quickly -quickstart: |- - Here's how to get started... +# quickstart: |- +# Here's how to get started... # Other files to include in this README from the project folder include: diff --git a/docs/terraform.md b/docs/terraform.md index 618b514..c01f2c9 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -18,14 +18,13 @@ | Name | Source | Version | |------|--------|---------| +| [kms\_key](#module\_kms\_key) | cloudposse/kms-key/aws | 0.12.1 | | [this](#module\_this) | cloudposse/label/null | 0.25.0 | ## Resources | Name | Type | |------|------| -| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | | [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -38,6 +37,7 @@ | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) The waiting period, specified in number of days.
After the waiting period ends, AWS KMS deletes the KMS key.
If you specify a value, it must be between 7 and 30, inclusive.
Defaults to `7`. | `number` | `7` | no | | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | @@ -53,11 +53,12 @@ | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | -| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | +| [zones](#input\_zones) | (Optional) A map of hosted zones with `zone_id` to assign the
KSK to in the format of:
{
"example.com" = {
zone_id = "Z8VLZEXAMPLE"
}
}
Defaults to `{}` which will generate the KMS key and alias but
not assign it to a hosted zone which can be useful for staging. | `map(map(string))` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [key\_arn](#output\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [this\_key\_arn](#output\_this\_key\_arn) | Deprecated: KMS key arn for Route53 DNSSEC CMK | diff --git a/examples/complete/fixtures.us-west-1.tfvars b/examples/complete/fixtures.us-west-1.tfvars new file mode 100644 index 0000000..56aea7e --- /dev/null +++ b/examples/complete/fixtures.us-west-1.tfvars @@ -0,0 +1,7 @@ +region = "us-west-1" + +namespace = "eg" + +stage = "test" + +name = "test-ksk" \ No newline at end of file diff --git a/examples/complete/main.tf b/examples/complete/main.tf index e69de29..b307d3e 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -0,0 +1,12 @@ +module "ksk" { + source = "../.." + context = module.this.context + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + providers = { + aws = aws.use1 + } +} \ No newline at end of file diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index e69de29..e7382a9 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -0,0 +1,4 @@ +output "key_arn" { + description = "KMS key arn for Route53 DNSSEC CMK" + value = module.kms_key.key_arn +} diff --git a/examples/complete/providers.tf b/examples/complete/providers.tf index e70fb2f..08520de 100644 --- a/examples/complete/providers.tf +++ b/examples/complete/providers.tf @@ -1,3 +1,8 @@ provider "aws" { + region = var.region +} + +provider "aws" { + alias = "use1" region = "us-east-1" -} \ No newline at end of file +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index e69de29..2fad651 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -0,0 +1,4 @@ +variable "region" { + type = string + description = "AWS region" +} \ No newline at end of file diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index e69de29..d051642 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 3.0" + # configuration_aliases = [aws.use1] + } + } + + required_version = ">= 0.13" +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 7e4a233..d20d1ef 100644 --- a/variables.tf +++ b/variables.tf @@ -1,12 +1,29 @@ variable "zones" { - description = "A list of Hosted Zone IDs to assign KSK to" + description = <<-EOT + (Optional) A map of hosted zones with `zone_id` to assign the + KSK to in the format of: + ``` + { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + ``` + Defaults to `{}` which will generate the KMS key and alias but + not assign it to a hosted zone which can be useful for staging. + EOT type = map(map(string)) default = {} } variable "deletion_window_in_days" { type = number - description = "(optional) describe your variable" + description = <<-EOT + (Optional) The waiting period, specified in number of days. + After the waiting period ends, AWS KMS deletes the KMS key. + If you specify a value, it must be between 7 and 30, inclusive. + Defaults to `7`. + EOT default = 7 }