├── .editorconfig
├── .github
└── workflows
│ ├── lock.yml
│ ├── pr-title.yml
│ ├── pre-commit.yml
│ ├── release.yml
│ └── stale-actions.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .releaserc.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── examples
├── README.md
└── complete
│ ├── README.md
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── main.tf
├── outputs.tf
├── variables.tf
├── versions.tf
└── wrappers
├── README.md
├── main.tf
├── outputs.tf
├── variables.tf
└── versions.tf
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 | # Uses editorconfig to maintain consistent coding styles
3 |
4 | # top-most EditorConfig file
5 | root = true
6 |
7 | # Unix-style newlines with a newline ending every file
8 | [*]
9 | charset = utf-8
10 | end_of_line = lf
11 | indent_size = 2
12 | indent_style = space
13 | insert_final_newline = true
14 | max_line_length = 80
15 | trim_trailing_whitespace = true
16 |
17 | [*.{tf,tfvars}]
18 | indent_size = 2
19 | indent_style = space
20 |
21 | [*.md]
22 | max_line_length = 0
23 | trim_trailing_whitespace = false
24 |
25 | [Makefile]
26 | tab_width = 2
27 | indent_style = tab
28 |
29 | [COMMIT_EDITMSG]
30 | max_line_length = 0
31 |
--------------------------------------------------------------------------------
/.github/workflows/lock.yml:
--------------------------------------------------------------------------------
1 | name: 'Lock Threads'
2 |
3 | on:
4 | schedule:
5 | - cron: '50 1 * * *'
6 |
7 | jobs:
8 | lock:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: dessant/lock-threads@v5
12 | with:
13 | github-token: ${{ secrets.GITHUB_TOKEN }}
14 | issue-comment: >
15 | I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
16 | If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
17 | issue-inactive-days: '30'
18 | pr-comment: >
19 | I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
20 | If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
21 | pr-inactive-days: '30'
22 |
--------------------------------------------------------------------------------
/.github/workflows/pr-title.yml:
--------------------------------------------------------------------------------
1 | name: 'Validate PR title'
2 |
3 | on:
4 | pull_request_target:
5 | types:
6 | - opened
7 | - edited
8 | - synchronize
9 |
10 | jobs:
11 | main:
12 | name: Validate PR title
13 | runs-on: ubuntu-latest
14 | steps:
15 | # Please look up the latest version from
16 | # https://github.com/amannn/action-semantic-pull-request/releases
17 | - uses: amannn/action-semantic-pull-request@v5.5.3
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 | with:
21 | # Configure which types are allowed.
22 | # Default: https://github.com/commitizen/conventional-commit-types
23 | types: |
24 | fix
25 | feat
26 | docs
27 | ci
28 | chore
29 | # Configure that a scope must always be provided.
30 | requireScope: false
31 | # Configure additional validation for the subject based on a regex.
32 | # This example ensures the subject starts with an uppercase character.
33 | subjectPattern: ^[A-Z].+$
34 | # If `subjectPattern` is configured, you can use this property to override
35 | # the default error message that is shown when the pattern doesn't match.
36 | # The variables `subject` and `title` can be used within the message.
37 | subjectPatternError: |
38 | The subject "{subject}" found in the pull request title "{title}"
39 | didn't match the configured pattern. Please ensure that the subject
40 | starts with an uppercase character.
41 | # For work-in-progress PRs you can typically use draft pull requests
42 | # from Github. However, private repositories on the free plan don't have
43 | # this option and therefore this action allows you to opt-in to using the
44 | # special "[WIP]" prefix to indicate this state. This will avoid the
45 | # validation of the PR title and the pull request checks remain pending.
46 | # Note that a second check will be reported if this is enabled.
47 | wip: true
48 | # When using "Squash and merge" on a PR with only one commit, GitHub
49 | # will suggest using that commit message instead of the PR title for the
50 | # merge commit, and it's easy to commit this by mistake. Enable this option
51 | # to also validate the commit message for one commit PRs.
52 | validateSingleCommit: false
53 |
--------------------------------------------------------------------------------
/.github/workflows/pre-commit.yml:
--------------------------------------------------------------------------------
1 | name: Pre-Commit
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | - master
8 |
9 | env:
10 | TERRAFORM_DOCS_VERSION: v0.19.0
11 | TFLINT_VERSION: v0.53.0
12 |
13 | jobs:
14 | collectInputs:
15 | name: Collect workflow inputs
16 | runs-on: ubuntu-latest
17 | outputs:
18 | directories: ${{ steps.dirs.outputs.directories }}
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 |
23 | - name: Get root directories
24 | id: dirs
25 | uses: clowdhaus/terraform-composite-actions/directories@v1.9.0
26 |
27 | preCommitMinVersions:
28 | name: Min TF pre-commit
29 | needs: collectInputs
30 | runs-on: ubuntu-latest
31 | strategy:
32 | matrix:
33 | directory: ${{ fromJson(needs.collectInputs.outputs.directories) }}
34 | steps:
35 | # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449
36 | - name: Delete huge unnecessary tools folder
37 | run: |
38 | rm -rf /opt/hostedtoolcache/CodeQL
39 | rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk
40 | rm -rf /opt/hostedtoolcache/Ruby
41 | rm -rf /opt/hostedtoolcache/go
42 |
43 | - name: Checkout
44 | uses: actions/checkout@v4
45 |
46 | - name: Terraform min/max versions
47 | id: minMax
48 | uses: clowdhaus/terraform-min-max@v1.3.1
49 | with:
50 | directory: ${{ matrix.directory }}
51 |
52 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }}
53 | # Run only validate pre-commit check on min version supported
54 | if: ${{ matrix.directory != '.' }}
55 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1
56 | with:
57 | terraform-version: ${{ steps.minMax.outputs.minVersion }}
58 | tflint-version: ${{ env.TFLINT_VERSION }}
59 | args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*'
60 |
61 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }}
62 | # Run only validate pre-commit check on min version supported
63 | if: ${{ matrix.directory == '.' }}
64 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1
65 | with:
66 | terraform-version: ${{ steps.minMax.outputs.minVersion }}
67 | tflint-version: ${{ env.TFLINT_VERSION }}
68 | args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)'
69 |
70 | preCommitMaxVersion:
71 | name: Max TF pre-commit
72 | runs-on: ubuntu-latest
73 | needs: collectInputs
74 | steps:
75 | # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449
76 | - name: Delete huge unnecessary tools folder
77 | run: |
78 | rm -rf /opt/hostedtoolcache/CodeQL
79 | rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk
80 | rm -rf /opt/hostedtoolcache/Ruby
81 | rm -rf /opt/hostedtoolcache/go
82 |
83 | - name: Checkout
84 | uses: actions/checkout@v4
85 | with:
86 | ref: ${{ github.event.pull_request.head.ref }}
87 | repository: ${{github.event.pull_request.head.repo.full_name}}
88 |
89 | - name: Terraform min/max versions
90 | id: minMax
91 | uses: clowdhaus/terraform-min-max@v1.3.1
92 |
93 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }}
94 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1
95 | with:
96 | terraform-version: ${{ steps.minMax.outputs.maxVersion }}
97 | tflint-version: ${{ env.TFLINT_VERSION }}
98 | terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }}
99 | install-hcledit: true
100 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | - master
9 | paths:
10 | - '**/*.tpl'
11 | - '**/*.py'
12 | - '**/*.tf'
13 | - '.github/workflows/release.yml'
14 |
15 | jobs:
16 | release:
17 | name: Release
18 | runs-on: ubuntu-latest
19 | # Skip running release workflow on forks
20 | if: github.repository_owner == 'terraform-aws-modules'
21 | steps:
22 | - name: Checkout
23 | uses: actions/checkout@v4
24 | with:
25 | persist-credentials: false
26 | fetch-depth: 0
27 |
28 | - name: Release
29 | uses: cycjimmy/semantic-release-action@v4
30 | with:
31 | semantic_version: 23.0.2
32 | extra_plugins: |
33 | @semantic-release/changelog@6.0.3
34 | @semantic-release/git@10.0.1
35 | conventional-changelog-conventionalcommits@7.0.2
36 | env:
37 | GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
38 |
--------------------------------------------------------------------------------
/.github/workflows/stale-actions.yaml:
--------------------------------------------------------------------------------
1 | name: 'Mark or close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '0 0 * * *'
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v9
11 | with:
12 | repo-token: ${{ secrets.GITHUB_TOKEN }}
13 | # Staling issues and PR's
14 | days-before-stale: 30
15 | stale-issue-label: stale
16 | stale-pr-label: stale
17 | stale-issue-message: |
18 | This issue has been automatically marked as stale because it has been open 30 days
19 | with no activity. Remove stale label or comment or this issue will be closed in 10 days
20 | stale-pr-message: |
21 | This PR has been automatically marked as stale because it has been open 30 days
22 | with no activity. Remove stale label or comment or this PR will be closed in 10 days
23 | # Not stale if have this labels or part of milestone
24 | exempt-issue-labels: bug,wip,on-hold
25 | exempt-pr-labels: bug,wip,on-hold
26 | exempt-all-milestones: true
27 | # Close issue operations
28 | # Label will be automatically removed if the issues are no longer closed nor locked.
29 | days-before-close: 10
30 | delete-branch: true
31 | close-issue-message: This issue was automatically closed because of stale in 10 days
32 | close-pr-message: This PR was automatically closed because of stale in 10 days
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Local .terraform directories
2 | **/.terraform/*
3 |
4 | # .tfstate files
5 | *.tfstate
6 | *.tfstate.*
7 |
8 | # terraform lockfile
9 | .terraform.lock.hcl
10 |
11 | # Crash log files
12 | crash.log
13 |
14 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as
15 | # password, private keys, and other secrets. These should not be part of version
16 | # control as they are data points which are potentially sensitive and subject
17 | # to change depending on the environment.
18 | #
19 | *.tfvars
20 |
21 | # Ignore override files as they are usually used to override resources locally and so
22 | # are not checked in
23 | override.tf
24 | override.tf.json
25 | *_override.tf
26 | *_override.tf.json
27 |
28 | # Include override files you do wish to add to version control using negated pattern
29 | #
30 | # !example_override.tf
31 |
32 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
33 | # example: *tfplan*
34 |
35 | # Ignore CLI configuration files
36 | .terraformrc
37 | terraform.rc
38 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/antonbabenko/pre-commit-terraform
3 | rev: v1.96.1
4 | hooks:
5 | - id: terraform_fmt
6 | - id: terraform_wrapper_module_for_each
7 | - id: terraform_docs
8 | args:
9 | - '--args=--lockfile=false'
10 | - id: terraform_tflint
11 | args:
12 | - '--args=--only=terraform_deprecated_interpolation'
13 | - '--args=--only=terraform_deprecated_index'
14 | - '--args=--only=terraform_unused_declarations'
15 | - '--args=--only=terraform_comment_syntax'
16 | - '--args=--only=terraform_documented_outputs'
17 | - '--args=--only=terraform_documented_variables'
18 | - '--args=--only=terraform_typed_variables'
19 | - '--args=--only=terraform_module_pinned_source'
20 | - '--args=--only=terraform_naming_convention'
21 | - '--args=--only=terraform_required_version'
22 | - '--args=--only=terraform_required_providers'
23 | - '--args=--only=terraform_standard_module_structure'
24 | - '--args=--only=terraform_workspace_remote'
25 | - id: terraform_validate
26 | - repo: https://github.com/pre-commit/pre-commit-hooks
27 | rev: v5.0.0
28 | hooks:
29 | - id: check-merge-conflict
30 | - id: end-of-file-fixer
31 | - id: trailing-whitespace
32 |
--------------------------------------------------------------------------------
/.releaserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "branches": [
3 | "main",
4 | "master"
5 | ],
6 | "ci": false,
7 | "plugins": [
8 | [
9 | "@semantic-release/commit-analyzer",
10 | {
11 | "preset": "conventionalcommits"
12 | }
13 | ],
14 | [
15 | "@semantic-release/release-notes-generator",
16 | {
17 | "preset": "conventionalcommits"
18 | }
19 | ],
20 | [
21 | "@semantic-release/github",
22 | {
23 | "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:",
24 | "labels": false,
25 | "releasedLabels": false
26 | }
27 | ],
28 | [
29 | "@semantic-release/changelog",
30 | {
31 | "changelogFile": "CHANGELOG.md",
32 | "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file."
33 | }
34 | ],
35 | [
36 | "@semantic-release/git",
37 | {
38 | "assets": [
39 | "CHANGELOG.md"
40 | ],
41 | "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
42 | }
43 | ]
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | ## [3.1.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v3.1.0...v3.1.1) (2024-10-11)
6 |
7 |
8 | ### Bug Fixes
9 |
10 | * Update CI workflow versions to latest ([#35](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/35)) ([c248050](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/c2480502618251c45ab8bcf6c57ec37bd08a8370))
11 |
12 | ## [3.1.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v3.0.0...v3.1.0) (2024-06-12)
13 |
14 |
15 | ### Features
16 |
17 | * Grants output marked as sensitive data ([#33](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/33)) ([965a52d](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/965a52d6686898897bce31d2f409e2ff9e8d5268))
18 |
19 | ## [3.0.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v2.2.1...v3.0.0) (2024-05-11)
20 |
21 |
22 | ### ⚠ BREAKING CHANGES
23 |
24 | * Support `rotation_period_in_days`, AWS Provider v5, Terraform MSV 1.3 (#32)
25 |
26 | ### Features
27 |
28 | * Support `rotation_period_in_days`, AWS Provider v5, Terraform MSV 1.3 ([#32](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/32)) ([f8c96ce](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/f8c96ce4bfc45fa2cb2e2cfa346d0d1930cdfce3))
29 |
30 | ## [2.2.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v2.2.0...v2.2.1) (2024-03-06)
31 |
32 |
33 | ### Bug Fixes
34 |
35 | * Update CI workflow versions to remove deprecated runtime warnings ([#28](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/28)) ([866950f](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/866950f91b3bc4411fa14d1f5c2c304145540d7f))
36 |
37 | ## [2.2.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v2.1.0...v2.2.0) (2024-02-02)
38 |
39 |
40 | ### Features
41 |
42 | * Add wrapper modules ([#26](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/26)) ([e6eba07](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/e6eba07467818a27670db60b3eb46f98dff19ef9))
43 |
44 | ## [2.1.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v2.0.1...v2.1.0) (2023-11-03)
45 |
46 |
47 | ### Features
48 |
49 | * Do not call data resources when `create` is `false` ([#25](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/25)) ([4951c38](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/4951c38f3cd569411eb53476ac8502981083f5d2))
50 |
51 | ### [2.0.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v2.0.0...v2.0.1) (2023-09-18)
52 |
53 |
54 | ### Bug Fixes
55 |
56 | * Default admin permissions for special keys ([#24](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/24)) ([c975efd](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/c975efda5686fd7c9fb98518332617e4876e5317))
57 |
58 | ## [2.0.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.5.0...v2.0.0) (2023-09-05)
59 |
60 |
61 | ### ⚠ BREAKING CHANGES
62 |
63 | * Added `custom_key_store_id`, bump version of AWS provider to 4.x (#23)
64 |
65 | ### Features
66 |
67 | * Added `custom_key_store_id`, bump version of AWS provider to 4.x ([#23](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/23)) ([beb5667](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/beb56674a6e5db7dfa6cf70c9e953183d6574472))
68 |
69 | ## [1.5.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.4.0...v1.5.0) (2023-02-09)
70 |
71 |
72 | ### Features
73 |
74 | * Add specific policy for Autoscaling service linked roles ([#15](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/15)) ([217ac76](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/217ac76868ac3624bb89e183372d25d2da67bd8b))
75 |
76 | ## [1.4.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.3.1...v1.4.0) (2023-01-28)
77 |
78 |
79 | ### Features
80 |
81 | * Support adding KMS replica keys ([#9](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/9)) ([9a7080b](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/9a7080bb00c468a55a85a0584648b51a68807024))
82 |
83 | ### [1.3.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.3.0...v1.3.1) (2023-01-24)
84 |
85 |
86 | ### Bug Fixes
87 |
88 | * Use a version for to avoid GitHub API rate limiting on CI workflows ([#12](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/12)) ([040736e](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/040736eca2e82f27ac1219dcf4f10ee0eb24ff6d))
89 |
90 | ## [1.3.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.2.2...v1.3.0) (2022-11-21)
91 |
92 |
93 | ### Features
94 |
95 | * Add support for creating customer managed keys used for Route53 DNSSEC signing ([#10](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/10)) ([d694450](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/d6944500aa33aafa19027facb1828ed3cf837196))
96 |
97 | ### [1.2.2](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.2.1...v1.2.2) (2022-11-07)
98 |
99 |
100 | ### Bug Fixes
101 |
102 | * Update CI configuration files to use latest version ([#8](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/8)) ([01bd36b](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/01bd36b2a07830fe91184c69f3e70c975a1fdd62))
103 |
104 | ### [1.2.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.2.0...v1.2.1) (2022-10-14)
105 |
106 |
107 | ### Bug Fixes
108 |
109 | * Modify `key_service_principals` to be generic to support conditions for confused deputy problem ([#7](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/7)) ([7b85239](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/7b85239466b365c31d7e976f82964789d4215c0e))
110 |
111 | ## [1.2.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.1.0...v1.2.0) (2022-10-14)
112 |
113 |
114 | ### Features
115 |
116 | * Adding Key Service Principals ([#6](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/6)) ([4841f28](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/4841f28bc1366a789df97f022b42881d5d73421d))
117 |
118 | ## [1.1.0](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.0.3...v1.1.0) (2022-08-17)
119 |
120 |
121 | ### Features
122 |
123 | * Add support for providing aliases using computed attributes ([#4](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/4)) ([8150812](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/81508121e16b9da133259763cca1fe98485a38b7))
124 |
125 | ### [1.0.3](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.0.2...v1.0.3) (2022-08-15)
126 |
127 |
128 | ### Bug Fixes
129 |
130 | * Add support for aliases and grants on `aws_kms_external_key` ([#3](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/3)) ([beea8d6](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/beea8d64e3680978785b1b0a93911c5d602f98fe))
131 |
132 | ### [1.0.2](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.0.1...v1.0.2) (2022-07-14)
133 |
134 |
135 | ### Bug Fixes
136 |
137 | * Correct boolean logic for enabling/disabling key owners policy statement ([#2](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/2)) ([944ea72](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/944ea72ac38f85af0a58f10650285958e78cac0c))
138 |
139 | ### [1.0.1](https://github.com/terraform-aws-modules/terraform-aws-kms/compare/v1.0.0...v1.0.1) (2022-06-28)
140 |
141 |
142 | ### Bug Fixes
143 |
144 | * Reduce required versions for Terraform and AWS provider ([#1](https://github.com/terraform-aws-modules/terraform-aws-kms/issues/1)) ([f80bc66](https://github.com/terraform-aws-modules/terraform-aws-kms/commit/f80bc665e11d7aabacc8be397e782a1dcc1e1148))
145 |
146 | ## 1.0.0 (2022-06-25)
147 |
148 |
149 | ### Features
150 |
151 | * Add support for external key using externally provided material ([2726c25](https://github.com/clowdhaus/terraform-aws-kms/commit/2726c2517fb203b6c3cf3b6e5cec00442336d88e))
152 | * Add support for source and override policy documents ([5a01134](https://github.com/clowdhaus/terraform-aws-kms/commit/5a01134f4358e55cd2b65bfd1a1b6d8c91988dc1))
153 | * Initial implementation of module ([a8a4f33](https://github.com/clowdhaus/terraform-aws-kms/commit/a8a4f33b95320b1d7457cefef3759f3544498f23))
154 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS KMS Terraform module
2 |
3 | Terraform module which creates AWS KMS resources.
4 |
5 | [](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
6 |
7 | ## Usage
8 |
9 | See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-kms/tree/master/examples) directory for working examples to reference:
10 |
11 | ### Autoscaling Service Linked Role
12 |
13 | Reference usage for EC2 AutoScaling service linked role to launch encrypted EBS volumes:
14 |
15 | ```hcl
16 | module "kms" {
17 | source = "terraform-aws-modules/kms/aws"
18 |
19 | description = "EC2 AutoScaling key usage"
20 | key_usage = "ENCRYPT_DECRYPT"
21 |
22 | # Policy
23 | key_administrators = ["arn:aws:iam::012345678901:role/admin"]
24 | key_service_roles_for_autoscaling = ["arn:aws:iam::012345678901:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"]
25 |
26 | # Aliases
27 | aliases = ["mycompany/ebs"]
28 |
29 | tags = {
30 | Terraform = "true"
31 | Environment = "dev"
32 | }
33 | }
34 | ```
35 |
36 | ### External Key
37 |
38 | Reference usage for external CMK (externally provided encryption material):
39 |
40 | ```hcl
41 | module "kms" {
42 | source = "terraform-aws-modules/kms/aws"
43 |
44 | description = "External key example"
45 | key_material_base64 = "Wblj06fduthWggmsT0cLVoIMOkeLbc2kVfMud77i/JY="
46 | valid_to = "2085-04-12T23:20:50.52Z"
47 |
48 | # Policy
49 | key_owners = ["arn:aws:iam::012345678901:role/owner"]
50 | key_administrators = ["arn:aws:iam::012345678901:role/admin"]
51 | key_users = ["arn:aws:iam::012345678901:role/user"]
52 | key_service_users = ["arn:aws:iam::012345678901:role/ec2-role"]
53 |
54 | # Aliases
55 | aliases = ["mycompany/external"]
56 | aliases_use_name_prefix = true
57 |
58 | # Grants
59 | grants = {
60 | lambda = {
61 | grantee_principal = "arn:aws:iam::012345678901:role/lambda-function"
62 | operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
63 | constraints = {
64 | encryption_context_equals = {
65 | Department = "Finance"
66 | }
67 | }
68 | }
69 | }
70 |
71 | tags = {
72 | Terraform = "true"
73 | Environment = "dev"
74 | }
75 | }
76 | ```
77 |
78 | ### Reference
79 |
80 | Reference usage showing available configurations.
81 |
82 | ```hcl
83 | module "kms" {
84 | source = "terraform-aws-modules/kms/aws"
85 |
86 | description = "Complete key example showing various configurations available"
87 | deletion_window_in_days = 7
88 | enable_key_rotation = true
89 | is_enabled = true
90 | key_usage = "ENCRYPT_DECRYPT"
91 | multi_region = false
92 |
93 | # Policy
94 | enable_default_policy = true
95 | key_owners = ["arn:aws:iam::012345678901:role/owner"]
96 | key_administrators = ["arn:aws:iam::012345678901:role/admin"]
97 | key_users = ["arn:aws:iam::012345678901:role/user"]
98 | key_service_users = ["arn:aws:iam::012345678901:role/ec2-role"]
99 | key_symmetric_encryption_users = ["arn:aws:iam::012345678901:role/symmetric-user"]
100 | key_hmac_users = ["arn:aws:iam::012345678901:role/hmac-user"]
101 | key_asymmetric_public_encryption_users = ["arn:aws:iam::012345678901:role/asymmetric-public-user"]
102 | key_asymmetric_sign_verify_users = ["arn:aws:iam::012345678901:role/sign-verify-user"]
103 |
104 | # Aliases
105 | aliases = ["one", "foo/bar"] # accepts static strings only
106 | computed_aliases = {
107 | ex = {
108 | # Sometimes you want to pass in an upstream attribute as the name and
109 | # that conflicts with using `for_each over a `toset()` since the value is not
110 | # known until after applying. Instead, we can use `computed_aliases` to work
111 | # around this limitation
112 | # Reference: https://github.com/hashicorp/terraform/issues/30937
113 | name = aws_iam_role.lambda.name
114 | }
115 | }
116 | aliases_use_name_prefix = true
117 |
118 | # Grants
119 | grants = {
120 | lambda = {
121 | grantee_principal = "arn:aws:iam::012345678901:role/lambda-function"
122 | operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
123 | constraints = {
124 | encryption_context_equals = {
125 | Department = "Finance"
126 | }
127 | }
128 | }
129 | }
130 |
131 | tags = {
132 | Terraform = "true"
133 | Environment = "dev"
134 | }
135 | }
136 | ```
137 |
138 | ## Examples
139 |
140 | Examples codified under the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-kms/tree/master/examples) are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module. If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you!
141 |
142 | - [Complete](https://github.com/terraform-aws-modules/terraform-aws-kms/tree/master/examples/complete)
143 |
144 |
145 | ## Requirements
146 |
147 | | Name | Version |
148 | |------|---------|
149 | | [terraform](#requirement\_terraform) | >= 1.3 |
150 | | [aws](#requirement\_aws) | >= 5.49 |
151 |
152 | ## Providers
153 |
154 | | Name | Version |
155 | |------|---------|
156 | | [aws](#provider\_aws) | >= 5.49 |
157 |
158 | ## Modules
159 |
160 | No modules.
161 |
162 | ## Resources
163 |
164 | | Name | Type |
165 | |------|------|
166 | | [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
167 | | [aws_kms_external_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_external_key) | resource |
168 | | [aws_kms_grant.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_grant) | resource |
169 | | [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
170 | | [aws_kms_replica_external_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_replica_external_key) | resource |
171 | | [aws_kms_replica_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_replica_key) | resource |
172 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
173 | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
174 | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
175 |
176 | ## Inputs
177 |
178 | | Name | Description | Type | Default | Required |
179 | |------|-------------|------|---------|:--------:|
180 | | [aliases](#input\_aliases) | A list of aliases to create. Note - due to the use of `toset()`, values must be static strings and not computed values | `list(string)` | `[]` | no |
181 | | [aliases\_use\_name\_prefix](#input\_aliases\_use\_name\_prefix) | Determines whether the alias name is used as a prefix | `bool` | `false` | no |
182 | | [bypass\_policy\_lockout\_safety\_check](#input\_bypass\_policy\_lockout\_safety\_check) | A flag to indicate whether to bypass the key policy lockout safety check. Setting this value to true increases the risk that the KMS key becomes unmanageable | `bool` | `null` | no |
183 | | [computed\_aliases](#input\_computed\_aliases) | A map of aliases to create. Values provided via the `name` key of the map can be computed from upstream resources | `any` | `{}` | no |
184 | | [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
185 | | [create\_external](#input\_create\_external) | Determines whether an external CMK (externally provided material) will be created or a standard CMK (AWS provided material) | `bool` | `false` | no |
186 | | [create\_replica](#input\_create\_replica) | Determines whether a replica standard CMK will be created (AWS provided material) | `bool` | `false` | no |
187 | | [create\_replica\_external](#input\_create\_replica\_external) | Determines whether a replica external CMK will be created (externally provided material) | `bool` | `false` | no |
188 | | [custom\_key\_store\_id](#input\_custom\_key\_store\_id) | ID of the KMS Custom Key Store where the key will be stored instead of KMS (eg CloudHSM). | `string` | `null` | no |
189 | | [customer\_master\_key\_spec](#input\_customer\_master\_key\_spec) | Specifies whether the key contains a symmetric key or an asymmetric key pair and the encryption algorithms or signing algorithms that the key supports. Valid values: `SYMMETRIC_DEFAULT`, `RSA_2048`, `RSA_3072`, `RSA_4096`, `HMAC_256`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`. Defaults to `SYMMETRIC_DEFAULT` | `string` | `null` | no |
190 | | [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | 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. If you do not specify a value, it defaults to `30` | `number` | `null` | no |
191 | | [description](#input\_description) | The description of the key as viewed in AWS console | `string` | `null` | no |
192 | | [enable\_default\_policy](#input\_enable\_default\_policy) | Specifies whether to enable the default key policy. Defaults to `true` | `bool` | `true` | no |
193 | | [enable\_key\_rotation](#input\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to `true` | `bool` | `true` | no |
194 | | [enable\_route53\_dnssec](#input\_enable\_route53\_dnssec) | Determines whether the KMS policy used for Route53 DNSSEC signing is enabled | `bool` | `false` | no |
195 | | [grants](#input\_grants) | A map of grant definitions to create | `any` | `{}` | no |
196 | | [is\_enabled](#input\_is\_enabled) | Specifies whether the key is enabled. Defaults to `true` | `bool` | `null` | no |
197 | | [key\_administrators](#input\_key\_administrators) | A list of IAM ARNs for [key administrators](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators) | `list(string)` | `[]` | no |
198 | | [key\_asymmetric\_public\_encryption\_users](#input\_key\_asymmetric\_public\_encryption\_users) | A list of IAM ARNs for [key asymmetric public encryption users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto) | `list(string)` | `[]` | no |
199 | | [key\_asymmetric\_sign\_verify\_users](#input\_key\_asymmetric\_sign\_verify\_users) | A list of IAM ARNs for [key asymmetric sign and verify users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto) | `list(string)` | `[]` | no |
200 | | [key\_hmac\_users](#input\_key\_hmac\_users) | A list of IAM ARNs for [key HMAC users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto) | `list(string)` | `[]` | no |
201 | | [key\_material\_base64](#input\_key\_material\_base64) | Base64 encoded 256-bit symmetric encryption key material to import. The CMK is permanently associated with this key material. External key only | `string` | `null` | no |
202 | | [key\_owners](#input\_key\_owners) | A list of IAM ARNs for those who will have full key permissions (`kms:*`) | `list(string)` | `[]` | no |
203 | | [key\_service\_roles\_for\_autoscaling](#input\_key\_service\_roles\_for\_autoscaling) | A list of IAM ARNs for [AWSServiceRoleForAutoScaling roles](https://docs.aws.amazon.com/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html#policy-example-cmk-access) | `list(string)` | `[]` | no |
204 | | [key\_service\_users](#input\_key\_service\_users) | A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration) | `list(string)` | `[]` | no |
205 | | [key\_statements](#input\_key\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | `any` | `{}` | no |
206 | | [key\_symmetric\_encryption\_users](#input\_key\_symmetric\_encryption\_users) | A list of IAM ARNs for [key symmetric encryption users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto) | `list(string)` | `[]` | no |
207 | | [key\_usage](#input\_key\_usage) | Specifies the intended use of the key. Valid values: `ENCRYPT_DECRYPT` or `SIGN_VERIFY`. Defaults to `ENCRYPT_DECRYPT` | `string` | `null` | no |
208 | | [key\_users](#input\_key\_users) | A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users) | `list(string)` | `[]` | no |
209 | | [multi\_region](#input\_multi\_region) | Indicates whether the KMS key is a multi-Region (`true`) or regional (`false`) key. Defaults to `false` | `bool` | `false` | no |
210 | | [override\_policy\_documents](#input\_override\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid` | `list(string)` | `[]` | no |
211 | | [policy](#input\_policy) | A valid policy JSON document. Although this is a key policy, not an IAM policy, an `aws_iam_policy_document`, in the form that designates a principal, can be used | `string` | `null` | no |
212 | | [primary\_external\_key\_arn](#input\_primary\_external\_key\_arn) | The primary external key arn of a multi-region replica external key | `string` | `null` | no |
213 | | [primary\_key\_arn](#input\_primary\_key\_arn) | The primary key arn of a multi-region replica key | `string` | `null` | no |
214 | | [rotation\_period\_in\_days](#input\_rotation\_period\_in\_days) | Custom period of time between each rotation date. Must be a number between 90 and 2560 (inclusive) | `number` | `null` | no |
215 | | [route53\_dnssec\_sources](#input\_route53\_dnssec\_sources) | A list of maps containing `account_ids` and Route53 `hosted_zone_arn` that will be allowed to sign DNSSEC records | `list(any)` | `[]` | no |
216 | | [source\_policy\_documents](#input\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
217 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
218 | | [valid\_to](#input\_valid\_to) | Time at which the imported key material expires. When the key material expires, AWS KMS deletes the key material and the CMK becomes unusable. If not specified, key material does not expire | `string` | `null` | no |
219 |
220 | ## Outputs
221 |
222 | | Name | Description |
223 | |------|-------------|
224 | | [aliases](#output\_aliases) | A map of aliases created and their attributes |
225 | | [external\_key\_expiration\_model](#output\_external\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
226 | | [external\_key\_state](#output\_external\_key\_state) | The state of the CMK |
227 | | [external\_key\_usage](#output\_external\_key\_usage) | The cryptographic operations for which you can use the CMK |
228 | | [grants](#output\_grants) | A map of grants created and their attributes |
229 | | [key\_arn](#output\_key\_arn) | The Amazon Resource Name (ARN) of the key |
230 | | [key\_id](#output\_key\_id) | The globally unique identifier for the key |
231 | | [key\_policy](#output\_key\_policy) | The IAM resource policy set on the key |
232 |
233 |
234 | ## License
235 |
236 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-kms/blob/master/LICENSE).
237 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | Please note - the examples provided serve two primary means:
4 |
5 | 1. Show users working examples of the various ways in which the module can be configured and features supported
6 | 2. A means of testing/validating module changes
7 |
8 | Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc.
9 |
--------------------------------------------------------------------------------
/examples/complete/README.md:
--------------------------------------------------------------------------------
1 | # Complete AWS KMS Example
2 |
3 | Configuration in this directory creates:
4 |
5 | - Complete KMS key example with key policy, aliases, and grants
6 | - External KMS key example
7 | - Default KMS key example with default policy
8 | - Disable KMS key example
9 |
10 | ## Usage
11 |
12 | To run this example you need to execute:
13 |
14 | ```bash
15 | $ terraform init
16 | $ terraform plan
17 | $ terraform apply
18 | ```
19 |
20 | Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
21 |
22 |
23 | ## Requirements
24 |
25 | | Name | Version |
26 | |------|---------|
27 | | [terraform](#requirement\_terraform) | >= 1.3 |
28 | | [aws](#requirement\_aws) | >= 5.49 |
29 |
30 | ## Providers
31 |
32 | | Name | Version |
33 | |------|---------|
34 | | [aws](#provider\_aws) | >= 5.49 |
35 |
36 | ## Modules
37 |
38 | | Name | Source | Version |
39 | |------|--------|---------|
40 | | [kms\_complete](#module\_kms\_complete) | ../.. | n/a |
41 | | [kms\_default](#module\_kms\_default) | ../.. | n/a |
42 | | [kms\_disabled](#module\_kms\_disabled) | ../.. | n/a |
43 | | [kms\_dnssec\_signing](#module\_kms\_dnssec\_signing) | ../.. | n/a |
44 | | [kms\_external](#module\_kms\_external) | ../.. | n/a |
45 | | [kms\_primary](#module\_kms\_primary) | ../.. | n/a |
46 | | [kms\_primary\_external](#module\_kms\_primary\_external) | ../.. | n/a |
47 | | [kms\_replica](#module\_kms\_replica) | ../.. | n/a |
48 | | [kms\_replica\_external](#module\_kms\_replica\_external) | ../.. | n/a |
49 |
50 | ## Resources
51 |
52 | | Name | Type |
53 | |------|------|
54 | | [aws_iam_role.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
55 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
56 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
57 |
58 | ## Inputs
59 |
60 | No inputs.
61 |
62 | ## Outputs
63 |
64 | | Name | Description |
65 | |------|-------------|
66 | | [complete\_aliases](#output\_complete\_aliases) | A map of aliases created and their attributes |
67 | | [complete\_external\_key\_expiration\_model](#output\_complete\_external\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
68 | | [complete\_external\_key\_state](#output\_complete\_external\_key\_state) | The state of the CMK |
69 | | [complete\_external\_key\_usage](#output\_complete\_external\_key\_usage) | The cryptographic operations for which you can use the CMK |
70 | | [complete\_grants](#output\_complete\_grants) | A map of grants created and their attributes |
71 | | [complete\_key\_arn](#output\_complete\_key\_arn) | The Amazon Resource Name (ARN) of the key |
72 | | [complete\_key\_id](#output\_complete\_key\_id) | The globally unique identifier for the key |
73 | | [complete\_key\_policy](#output\_complete\_key\_policy) | The IAM resource policy set on the key |
74 | | [default\_aliases](#output\_default\_aliases) | A map of aliases created and their attributes |
75 | | [default\_external\_key\_expiration\_model](#output\_default\_external\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
76 | | [default\_external\_key\_state](#output\_default\_external\_key\_state) | The state of the CMK |
77 | | [default\_external\_key\_usage](#output\_default\_external\_key\_usage) | The cryptographic operations for which you can use the CMK |
78 | | [default\_grants](#output\_default\_grants) | A map of grants created and their attributes |
79 | | [default\_key\_arn](#output\_default\_key\_arn) | The Amazon Resource Name (ARN) of the key |
80 | | [default\_key\_id](#output\_default\_key\_id) | The globally unique identifier for the key |
81 | | [default\_key\_policy](#output\_default\_key\_policy) | The IAM resource policy set on the key |
82 | | [external\_aliases](#output\_external\_aliases) | A map of aliases created and their attributes |
83 | | [external\_external\_key\_expiration\_model](#output\_external\_external\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
84 | | [external\_external\_key\_state](#output\_external\_external\_key\_state) | The state of the CMK |
85 | | [external\_external\_key\_usage](#output\_external\_external\_key\_usage) | The cryptographic operations for which you can use the CMK |
86 | | [external\_grants](#output\_external\_grants) | A map of grants created and their attributes |
87 | | [external\_key\_arn](#output\_external\_key\_arn) | The Amazon Resource Name (ARN) of the key |
88 | | [external\_key\_id](#output\_external\_key\_id) | The globally unique identifier for the key |
89 | | [external\_key\_policy](#output\_external\_key\_policy) | The IAM resource policy set on the key |
90 | | [replica\_aliases](#output\_replica\_aliases) | A map of aliases created and their attributes |
91 | | [replica\_external\_aliases](#output\_replica\_external\_aliases) | A map of aliases created and their attributes |
92 | | [replica\_external\_arn](#output\_replica\_external\_arn) | The Amazon Resource Name (ARN) of the key |
93 | | [replica\_external\_grants](#output\_replica\_external\_grants) | A map of grants created and their attributes |
94 | | [replica\_external\_key\_expiration\_model](#output\_replica\_external\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
95 | | [replica\_external\_key\_id](#output\_replica\_external\_key\_id) | The globally unique identifier for the key |
96 | | [replica\_external\_key\_policy](#output\_replica\_external\_key\_policy) | The IAM resource policy set on the key |
97 | | [replica\_external\_key\_state](#output\_replica\_external\_key\_state) | The state of the CMK |
98 | | [replica\_external\_key\_usage](#output\_replica\_external\_key\_usage) | The cryptographic operations for which you can use the CMK |
99 | | [replica\_grants](#output\_replica\_grants) | A map of grants created and their attributes |
100 | | [replica\_key\_arn](#output\_replica\_key\_arn) | The Amazon Resource Name (ARN) of the key |
101 | | [replica\_key\_expiration\_model](#output\_replica\_key\_expiration\_model) | Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE` |
102 | | [replica\_key\_id](#output\_replica\_key\_id) | The globally unique identifier for the key |
103 | | [replica\_key\_policy](#output\_replica\_key\_policy) | The IAM resource policy set on the key |
104 | | [replica\_key\_state](#output\_replica\_key\_state) | The state of the CMK |
105 | | [replica\_key\_usage](#output\_replica\_key\_usage) | The cryptographic operations for which you can use the CMK |
106 |
107 |
108 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-kms/blob/master/LICENSE).
109 |
--------------------------------------------------------------------------------
/examples/complete/main.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = local.region
3 | }
4 |
5 | locals {
6 | region = "us-east-1"
7 | name = "kms-ex-${replace(basename(path.cwd), "_", "-")}"
8 | current_identity = data.aws_caller_identity.current.arn
9 |
10 | tags = {
11 | Name = local.name
12 | Example = "complete"
13 | Repository = "https://github.com/terraform-aws-modules/terraform-aws-kms"
14 | }
15 | }
16 |
17 | data "aws_caller_identity" "current" {}
18 | data "aws_region" "current" {}
19 |
20 | ################################################################################
21 | # KMS Module
22 | ################################################################################
23 |
24 | module "kms_complete" {
25 | source = "../.."
26 |
27 | deletion_window_in_days = 7
28 | description = "Complete key example showing various configurations available"
29 | enable_key_rotation = false
30 | is_enabled = true
31 | key_usage = "ENCRYPT_DECRYPT"
32 | multi_region = false
33 |
34 | # Policy
35 | enable_default_policy = true
36 | key_owners = [local.current_identity]
37 | key_administrators = [local.current_identity]
38 | key_users = [local.current_identity]
39 | key_service_users = [local.current_identity]
40 | key_service_roles_for_autoscaling = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"]
41 | key_symmetric_encryption_users = [local.current_identity]
42 | key_hmac_users = [local.current_identity]
43 | key_asymmetric_public_encryption_users = [local.current_identity]
44 | key_asymmetric_sign_verify_users = [local.current_identity]
45 | key_statements = [
46 | {
47 | sid = "CloudWatchLogs"
48 | actions = [
49 | "kms:Encrypt*",
50 | "kms:Decrypt*",
51 | "kms:ReEncrypt*",
52 | "kms:GenerateDataKey*",
53 | "kms:Describe*"
54 | ]
55 | resources = ["*"]
56 |
57 | principals = [
58 | {
59 | type = "Service"
60 | identifiers = ["logs.${data.aws_region.current.name}.amazonaws.com"]
61 | }
62 | ]
63 |
64 | conditions = [
65 | {
66 | test = "ArnLike"
67 | variable = "kms:EncryptionContext:aws:logs:arn"
68 | values = [
69 | "arn:aws:logs:${local.region}:${data.aws_caller_identity.current.account_id}:log-group:*",
70 | ]
71 | }
72 | ]
73 | }
74 | ]
75 |
76 | # Aliases
77 | aliases = ["one", "foo/bar"]
78 | computed_aliases = {
79 | ex = {
80 | # Sometimes you want to pass in an upstream attribute as the name and
81 | # that conflicts with using `for_each over a `toset()` since the value is not
82 | # known until after applying. Instead, we can use `computed_aliases` to work
83 | # around this limitation
84 | # Reference: https://github.com/hashicorp/terraform/issues/30937
85 | name = aws_iam_role.lambda.name
86 | }
87 | }
88 | aliases_use_name_prefix = true
89 |
90 | # Grants
91 | grants = {
92 | lambda = {
93 | grantee_principal = aws_iam_role.lambda.arn
94 | operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
95 | constraints = {
96 | encryption_context_equals = {
97 | Department = "Finance"
98 | }
99 | }
100 | }
101 | }
102 |
103 | tags = local.tags
104 | }
105 |
106 | module "kms_external" {
107 | source = "../.."
108 |
109 | deletion_window_in_days = 7
110 | description = "External key example"
111 | create_external = true
112 | is_enabled = true
113 | key_material_base64 = "Wblj06fduthWggmsT0cLVoIMOkeLbc2kVfMud77i/JY="
114 | multi_region = false
115 | valid_to = "2023-11-21T23:20:50Z"
116 |
117 | tags = local.tags
118 | }
119 |
120 | module "kms_dnssec_signing" {
121 | source = "../.."
122 |
123 | description = "CMK for Route53 DNSSEC signing"
124 |
125 | key_usage = "SIGN_VERIFY"
126 | customer_master_key_spec = "ECC_NIST_P256"
127 |
128 | enable_route53_dnssec = true
129 | enable_key_rotation = false
130 | route53_dnssec_sources = [
131 | {
132 | accounts_ids = [data.aws_caller_identity.current.account_id] # can ommit if using current account ID which is default
133 | hosted_zone_arn = "arn:aws:route53:::hostedzone/*" # can ommit, this is default value
134 | }
135 | ]
136 |
137 | aliases = ["route53/dnssec-ex"]
138 |
139 | tags = local.tags
140 | }
141 |
142 | module "kms_default" {
143 | source = "../.."
144 |
145 | tags = local.tags
146 | }
147 |
148 | module "kms_disabled" {
149 | source = "../.."
150 |
151 | create = false
152 | }
153 |
154 | ################################################################################
155 | # Replica Key Example
156 | ################################################################################
157 |
158 | module "kms_primary" {
159 | source = "../.."
160 |
161 | deletion_window_in_days = 7
162 | description = "Primary key of replica key example"
163 | enable_key_rotation = false
164 | is_enabled = true
165 | key_usage = "ENCRYPT_DECRYPT"
166 | multi_region = true
167 |
168 | aliases = ["primary-standard"]
169 |
170 | tags = local.tags
171 | }
172 |
173 | provider "aws" {
174 | region = "eu-west-1"
175 | alias = "replica"
176 | }
177 |
178 | module "kms_replica" {
179 | source = "../.."
180 |
181 | deletion_window_in_days = 7
182 | description = "Replica key example showing various configurations available"
183 | create_replica = true
184 | primary_key_arn = module.kms_primary.key_arn
185 | enable_default_policy = true
186 |
187 | key_owners = [local.current_identity]
188 | key_administrators = [local.current_identity]
189 | key_users = [local.current_identity]
190 |
191 | # Aliases
192 | aliases = ["replica-standard"]
193 | computed_aliases = {
194 | ex = {
195 | # Sometimes you want to pass in an upstream attribute as the name and
196 | # that conflicts with using `for_each over a `toset()` since the value is not
197 | # known until after applying. Instead, we can use `computed_aliases` to work
198 | # around this limitation
199 | # Reference: https://github.com/hashicorp/terraform/issues/30937
200 | name = aws_iam_role.lambda.name
201 | }
202 | }
203 |
204 | # Grants
205 | grants = {
206 | lambda = {
207 | grantee_principal = aws_iam_role.lambda.arn
208 | operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
209 | constraints = {
210 | encryption_context_equals = {
211 | Department = "Finance"
212 | }
213 | }
214 | }
215 | }
216 |
217 | tags = local.tags
218 |
219 | providers = {
220 | aws = aws.replica
221 | }
222 | }
223 |
224 | ################################################################################
225 | # Replica External Key Example
226 | ################################################################################
227 |
228 | module "kms_primary_external" {
229 | source = "../.."
230 |
231 | deletion_window_in_days = 7
232 | description = "Primary external key of replica external key example"
233 | is_enabled = true
234 | create_external = true
235 | key_material_base64 = "Wblj06fduthWggmsT0cLVoIMOkeLbc2kVfMud77i/JY="
236 | multi_region = true
237 | valid_to = "2023-11-21T23:20:50Z"
238 |
239 | aliases = ["primary-external"]
240 |
241 | tags = local.tags
242 | }
243 |
244 | module "kms_replica_external" {
245 | source = "../.."
246 |
247 | deletion_window_in_days = 7
248 | description = "Replica external key example showing various configurations available"
249 | create_replica_external = true
250 | is_enabled = true
251 | # key material must be the same as the primary's
252 | key_material_base64 = "Wblj06fduthWggmsT0cLVoIMOkeLbc2kVfMud77i/JY="
253 | primary_external_key_arn = module.kms_primary_external.key_arn
254 | valid_to = "2023-11-21T23:20:50Z"
255 |
256 | aliases = ["replica-external"]
257 |
258 | # Grants
259 | grants = {
260 | lambda = {
261 | grantee_principal = aws_iam_role.lambda.arn
262 | operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
263 | constraints = {
264 | encryption_context_equals = {
265 | Department = "Finance"
266 | }
267 | }
268 | }
269 | }
270 |
271 | tags = local.tags
272 |
273 | providers = {
274 | aws = aws.replica
275 | }
276 | }
277 |
278 | ################################################################################
279 | # Supporting Resources
280 | ################################################################################
281 |
282 | resource "aws_iam_role" "lambda" {
283 | name_prefix = local.name
284 |
285 | assume_role_policy = jsonencode({
286 | Version = "2012-10-17"
287 | Statement = [
288 | {
289 | Effect = "Allow"
290 | Action = "sts:AssumeRole"
291 | Principal = {
292 | Service = "lambda.amazonaws.com"
293 | }
294 | }
295 | ]
296 | })
297 | }
298 |
--------------------------------------------------------------------------------
/examples/complete/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Complete
3 | ################################################################################
4 |
5 | output "complete_key_arn" {
6 | description = "The Amazon Resource Name (ARN) of the key"
7 | value = module.kms_complete.key_arn
8 | }
9 |
10 | output "complete_key_id" {
11 | description = "The globally unique identifier for the key"
12 | value = module.kms_complete.key_id
13 | }
14 |
15 | output "complete_key_policy" {
16 | description = "The IAM resource policy set on the key"
17 | value = module.kms_complete.key_policy
18 | }
19 |
20 | output "complete_external_key_expiration_model" {
21 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
22 | value = module.kms_complete.external_key_expiration_model
23 | }
24 |
25 | output "complete_external_key_state" {
26 | description = "The state of the CMK"
27 | value = module.kms_complete.external_key_state
28 | }
29 |
30 | output "complete_external_key_usage" {
31 | description = "The cryptographic operations for which you can use the CMK"
32 | value = module.kms_complete.external_key_usage
33 | }
34 |
35 | output "complete_aliases" {
36 | description = "A map of aliases created and their attributes"
37 | value = module.kms_complete.aliases
38 | }
39 |
40 | output "complete_grants" {
41 | description = "A map of grants created and their attributes"
42 | value = module.kms_complete.grants
43 | }
44 |
45 | ################################################################################
46 | # External
47 | ################################################################################
48 |
49 | output "external_key_arn" {
50 | description = "The Amazon Resource Name (ARN) of the key"
51 | value = module.kms_external.key_arn
52 | }
53 |
54 | output "external_key_id" {
55 | description = "The globally unique identifier for the key"
56 | value = module.kms_external.key_id
57 | }
58 |
59 | output "external_key_policy" {
60 | description = "The IAM resource policy set on the key"
61 | value = module.kms_external.key_policy
62 | }
63 |
64 | output "external_external_key_expiration_model" {
65 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
66 | value = module.kms_external.external_key_expiration_model
67 | }
68 |
69 | output "external_external_key_state" {
70 | description = "The state of the CMK"
71 | value = module.kms_external.external_key_state
72 | }
73 |
74 | output "external_external_key_usage" {
75 | description = "The cryptographic operations for which you can use the CMK"
76 | value = module.kms_external.external_key_usage
77 | }
78 |
79 | output "external_aliases" {
80 | description = "A map of aliases created and their attributes"
81 | value = module.kms_external.aliases
82 | }
83 |
84 | output "external_grants" {
85 | description = "A map of grants created and their attributes"
86 | value = module.kms_external.grants
87 | }
88 |
89 | ################################################################################
90 | # Default
91 | ################################################################################
92 |
93 | output "default_key_arn" {
94 | description = "The Amazon Resource Name (ARN) of the key"
95 | value = module.kms_default.key_arn
96 | }
97 |
98 | output "default_key_id" {
99 | description = "The globally unique identifier for the key"
100 | value = module.kms_default.key_id
101 | }
102 |
103 | output "default_key_policy" {
104 | description = "The IAM resource policy set on the key"
105 | value = module.kms_default.key_policy
106 | }
107 |
108 | output "default_external_key_expiration_model" {
109 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
110 | value = module.kms_default.external_key_expiration_model
111 | }
112 |
113 | output "default_external_key_state" {
114 | description = "The state of the CMK"
115 | value = module.kms_default.external_key_state
116 | }
117 |
118 | output "default_external_key_usage" {
119 | description = "The cryptographic operations for which you can use the CMK"
120 | value = module.kms_default.external_key_usage
121 | }
122 |
123 | output "default_aliases" {
124 | description = "A map of aliases created and their attributes"
125 | value = module.kms_default.aliases
126 | }
127 |
128 | output "default_grants" {
129 | description = "A map of grants created and their attributes"
130 | value = module.kms_default.grants
131 | }
132 |
133 |
134 | ################################################################################
135 | # Replica
136 | ################################################################################
137 |
138 | output "replica_key_arn" {
139 | description = "The Amazon Resource Name (ARN) of the key"
140 | value = module.kms_replica.key_arn
141 | }
142 |
143 | output "replica_key_id" {
144 | description = "The globally unique identifier for the key"
145 | value = module.kms_replica.key_id
146 | }
147 |
148 | output "replica_key_policy" {
149 | description = "The IAM resource policy set on the key"
150 | value = module.kms_replica.key_policy
151 | }
152 |
153 | output "replica_key_expiration_model" {
154 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
155 | value = module.kms_replica.external_key_expiration_model
156 | }
157 |
158 | output "replica_key_state" {
159 | description = "The state of the CMK"
160 | value = module.kms_replica.external_key_state
161 | }
162 |
163 | output "replica_key_usage" {
164 | description = "The cryptographic operations for which you can use the CMK"
165 | value = module.kms_replica.external_key_usage
166 | }
167 |
168 | output "replica_aliases" {
169 | description = "A map of aliases created and their attributes"
170 | value = module.kms_replica.aliases
171 | }
172 |
173 | output "replica_grants" {
174 | description = "A map of grants created and their attributes"
175 | value = module.kms_replica.grants
176 | }
177 |
178 |
179 | ################################################################################
180 | # Replica External
181 | ################################################################################
182 |
183 | output "replica_external_arn" {
184 | description = "The Amazon Resource Name (ARN) of the key"
185 | value = module.kms_replica_external.key_arn
186 | }
187 |
188 | output "replica_external_key_id" {
189 | description = "The globally unique identifier for the key"
190 | value = module.kms_replica_external.key_id
191 | }
192 |
193 | output "replica_external_key_policy" {
194 | description = "The IAM resource policy set on the key"
195 | value = module.kms_replica_external.key_policy
196 | }
197 |
198 | output "replica_external_key_expiration_model" {
199 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
200 | value = module.kms_replica_external.external_key_expiration_model
201 | }
202 |
203 | output "replica_external_key_state" {
204 | description = "The state of the CMK"
205 | value = module.kms_replica_external.external_key_state
206 | }
207 |
208 | output "replica_external_key_usage" {
209 | description = "The cryptographic operations for which you can use the CMK"
210 | value = module.kms_replica_external.external_key_usage
211 | }
212 |
213 | output "replica_external_aliases" {
214 | description = "A map of aliases created and their attributes"
215 | value = module.kms_replica_external.aliases
216 | }
217 |
218 | output "replica_external_grants" {
219 | description = "A map of grants created and their attributes"
220 | value = module.kms_replica_external.grants
221 | }
222 |
--------------------------------------------------------------------------------
/examples/complete/variables.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-kms/c20bffd41ce9716140cb9938faf0aa147b38ca2a/examples/complete/variables.tf
--------------------------------------------------------------------------------
/examples/complete/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.3"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 5.49"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | data "aws_partition" "current" {
2 | count = var.create ? 1 : 0
3 | }
4 | data "aws_caller_identity" "current" {
5 | count = var.create ? 1 : 0
6 | }
7 |
8 | locals {
9 | account_id = try(data.aws_caller_identity.current[0].account_id, "")
10 | partition = try(data.aws_partition.current[0].partition, "")
11 | dns_suffix = try(data.aws_partition.current[0].dns_suffix, "")
12 | }
13 |
14 | ################################################################################
15 | # Key
16 | ################################################################################
17 |
18 | resource "aws_kms_key" "this" {
19 | count = var.create && !var.create_external && !var.create_replica && !var.create_replica_external ? 1 : 0
20 |
21 | bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check
22 | customer_master_key_spec = var.customer_master_key_spec
23 | custom_key_store_id = var.custom_key_store_id
24 | deletion_window_in_days = var.deletion_window_in_days
25 | description = var.description
26 | enable_key_rotation = var.enable_key_rotation
27 | is_enabled = var.is_enabled
28 | key_usage = var.key_usage
29 | multi_region = var.multi_region
30 | policy = coalesce(var.policy, data.aws_iam_policy_document.this[0].json)
31 | rotation_period_in_days = var.rotation_period_in_days
32 |
33 | tags = var.tags
34 | }
35 |
36 | ################################################################################
37 | # External Key
38 | ################################################################################
39 |
40 | resource "aws_kms_external_key" "this" {
41 | count = var.create && var.create_external && !var.create_replica && !var.create_replica_external ? 1 : 0
42 |
43 | bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check
44 | deletion_window_in_days = var.deletion_window_in_days
45 | description = var.description
46 | enabled = var.is_enabled
47 | key_material_base64 = var.key_material_base64
48 | multi_region = var.multi_region
49 | policy = coalesce(var.policy, data.aws_iam_policy_document.this[0].json)
50 | valid_to = var.valid_to
51 |
52 | tags = var.tags
53 | }
54 |
55 | ################################################################################
56 | # Replica Key
57 | ################################################################################
58 |
59 | resource "aws_kms_replica_key" "this" {
60 | count = var.create && var.create_replica && !var.create_external && !var.create_replica_external ? 1 : 0
61 |
62 | bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check
63 | deletion_window_in_days = var.deletion_window_in_days
64 | description = var.description
65 | primary_key_arn = var.primary_key_arn
66 | enabled = var.is_enabled
67 | policy = coalesce(var.policy, data.aws_iam_policy_document.this[0].json)
68 |
69 | tags = var.tags
70 | }
71 |
72 | ################################################################################
73 | # Replica External Key
74 | ################################################################################
75 |
76 | resource "aws_kms_replica_external_key" "this" {
77 | count = var.create && !var.create_replica && !var.create_external && var.create_replica_external ? 1 : 0
78 |
79 | bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check
80 | deletion_window_in_days = var.deletion_window_in_days
81 | description = var.description
82 | enabled = var.is_enabled
83 | key_material_base64 = var.key_material_base64
84 | policy = coalesce(var.policy, data.aws_iam_policy_document.this[0].json)
85 | primary_key_arn = var.primary_external_key_arn
86 | valid_to = var.valid_to
87 |
88 | tags = var.tags
89 | }
90 |
91 | ################################################################################
92 | # Policy
93 | ################################################################################
94 |
95 | data "aws_iam_policy_document" "this" {
96 | count = var.create ? 1 : 0
97 |
98 | source_policy_documents = var.source_policy_documents
99 | override_policy_documents = var.override_policy_documents
100 |
101 | # Default policy - account wide access to all key operations
102 | dynamic "statement" {
103 | for_each = var.enable_default_policy ? [1] : []
104 |
105 | content {
106 | sid = "Default"
107 | actions = ["kms:*"]
108 | resources = ["*"]
109 |
110 | principals {
111 | type = "AWS"
112 | identifiers = ["arn:${local.partition}:iam::${local.account_id}:root"]
113 | }
114 | }
115 | }
116 |
117 | # Key owner - all key operations
118 | dynamic "statement" {
119 | for_each = length(var.key_owners) > 0 ? [1] : []
120 |
121 | content {
122 | sid = "KeyOwner"
123 | actions = ["kms:*"]
124 | resources = ["*"]
125 |
126 | principals {
127 | type = "AWS"
128 | identifiers = var.key_owners
129 | }
130 | }
131 | }
132 |
133 | # Key administrators - https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators
134 | dynamic "statement" {
135 | for_each = length(var.key_administrators) > 0 ? [1] : []
136 |
137 | content {
138 | sid = "KeyAdministration"
139 | actions = [
140 | "kms:Create*",
141 | "kms:Describe*",
142 | "kms:Enable*",
143 | "kms:List*",
144 | "kms:Put*",
145 | "kms:Update*",
146 | "kms:Revoke*",
147 | "kms:Disable*",
148 | "kms:Get*",
149 | "kms:Delete*",
150 | "kms:TagResource",
151 | "kms:UntagResource",
152 | "kms:ScheduleKeyDeletion",
153 | "kms:CancelKeyDeletion",
154 | "kms:ReplicateKey",
155 | "kms:ImportKeyMaterial"
156 | ]
157 | resources = ["*"]
158 |
159 | principals {
160 | type = "AWS"
161 | identifiers = var.key_administrators
162 | }
163 | }
164 | }
165 |
166 | # Key users - https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users
167 | dynamic "statement" {
168 | for_each = length(var.key_users) > 0 ? [1] : []
169 |
170 | content {
171 | sid = "KeyUsage"
172 | actions = [
173 | "kms:Encrypt",
174 | "kms:Decrypt",
175 | "kms:ReEncrypt*",
176 | "kms:GenerateDataKey*",
177 | "kms:DescribeKey",
178 | ]
179 | resources = ["*"]
180 |
181 | principals {
182 | type = "AWS"
183 | identifiers = var.key_users
184 | }
185 | }
186 | }
187 |
188 | # Key service users - https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration
189 | dynamic "statement" {
190 | for_each = length(var.key_service_users) > 0 ? [1] : []
191 |
192 | content {
193 | sid = "KeyServiceUsage"
194 | actions = [
195 | "kms:CreateGrant",
196 | "kms:ListGrants",
197 | "kms:RevokeGrant",
198 | ]
199 | resources = ["*"]
200 |
201 | principals {
202 | type = "AWS"
203 | identifiers = var.key_service_users
204 | }
205 |
206 | condition {
207 | test = "Bool"
208 | variable = "kms:GrantIsForAWSResource"
209 | values = [true]
210 | }
211 | }
212 | }
213 |
214 | # Key service roles for autoscaling - https://docs.aws.amazon.com/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html#policy-example-cmk-access
215 | dynamic "statement" {
216 | for_each = length(var.key_service_roles_for_autoscaling) > 0 ? [1] : []
217 |
218 | content {
219 | sid = "KeyServiceRolesASG"
220 | actions = [
221 | "kms:Encrypt",
222 | "kms:Decrypt",
223 | "kms:ReEncrypt*",
224 | "kms:GenerateDataKey*",
225 | "kms:DescribeKey",
226 | ]
227 | resources = ["*"]
228 |
229 | principals {
230 | type = "AWS"
231 | identifiers = var.key_service_roles_for_autoscaling
232 | }
233 | }
234 | }
235 |
236 | dynamic "statement" {
237 | for_each = length(var.key_service_roles_for_autoscaling) > 0 ? [1] : []
238 |
239 | content {
240 | sid = "KeyServiceRolesASGPersistentVol"
241 | actions = [
242 | "kms:CreateGrant"
243 | ]
244 | resources = ["*"]
245 |
246 | principals {
247 | type = "AWS"
248 | identifiers = var.key_service_roles_for_autoscaling
249 | }
250 |
251 | condition {
252 | test = "Bool"
253 | variable = "kms:GrantIsForAWSResource"
254 | values = [true]
255 | }
256 | }
257 | }
258 |
259 | # Key cryptographic operations - https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto
260 | dynamic "statement" {
261 | for_each = length(var.key_symmetric_encryption_users) > 0 ? [1] : []
262 |
263 | content {
264 | sid = "KeySymmetricEncryption"
265 | actions = [
266 | "kms:Decrypt",
267 | "kms:DescribeKey",
268 | "kms:Encrypt",
269 | "kms:GenerateDataKey*",
270 | "kms:ReEncrypt*",
271 | ]
272 | resources = ["*"]
273 |
274 | principals {
275 | type = "AWS"
276 | identifiers = var.key_symmetric_encryption_users
277 | }
278 | }
279 | }
280 |
281 | dynamic "statement" {
282 | for_each = length(var.key_hmac_users) > 0 ? [1] : []
283 |
284 | content {
285 | sid = "KeyHMAC"
286 | actions = [
287 | "kms:DescribeKey",
288 | "kms:GenerateMac",
289 | "kms:VerifyMac",
290 | ]
291 | resources = ["*"]
292 |
293 | principals {
294 | type = "AWS"
295 | identifiers = var.key_hmac_users
296 | }
297 | }
298 | }
299 |
300 | dynamic "statement" {
301 | for_each = length(var.key_asymmetric_public_encryption_users) > 0 ? [1] : []
302 |
303 | content {
304 | sid = "KeyAsymmetricPublicEncryption"
305 | actions = [
306 | "kms:Encrypt",
307 | "kms:Decrypt",
308 | "kms:ReEncrypt*",
309 | "kms:DescribeKey",
310 | "kms:GetPublicKey",
311 | ]
312 | resources = ["*"]
313 |
314 | principals {
315 | type = "AWS"
316 | identifiers = var.key_asymmetric_public_encryption_users
317 | }
318 | }
319 | }
320 |
321 | dynamic "statement" {
322 | for_each = length(var.key_asymmetric_sign_verify_users) > 0 ? [1] : []
323 |
324 | content {
325 | sid = "KeyAsymmetricSignVerify"
326 | actions = [
327 | "kms:DescribeKey",
328 | "kms:GetPublicKey",
329 | "kms:Sign",
330 | "kms:Verify",
331 | ]
332 | resources = ["*"]
333 |
334 | principals {
335 | type = "AWS"
336 | identifiers = var.key_asymmetric_sign_verify_users
337 | }
338 | }
339 | }
340 |
341 | # https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/access-control-managing-permissions.html#KMS-key-policy-for-DNSSEC
342 | dynamic "statement" {
343 | for_each = var.enable_route53_dnssec ? [1] : []
344 |
345 | content {
346 | sid = "Route53DnssecService"
347 | actions = [
348 | "kms:DescribeKey",
349 | "kms:GetPublicKey",
350 | "kms:Sign",
351 | ]
352 | resources = ["*"]
353 |
354 | principals {
355 | type = "Service"
356 | identifiers = ["dnssec-route53.${local.dns_suffix}"]
357 | }
358 | }
359 | }
360 |
361 | # https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/access-control-managing-permissions.html#KMS-key-policy-for-DNSSEC
362 | dynamic "statement" {
363 | for_each = var.enable_route53_dnssec ? [1] : []
364 |
365 | content {
366 | sid = "Route53DnssecGrant"
367 | actions = ["kms:CreateGrant"]
368 | resources = ["*"]
369 |
370 | principals {
371 | type = "Service"
372 | identifiers = ["dnssec-route53.${local.dns_suffix}"]
373 | }
374 |
375 | condition {
376 | test = "Bool"
377 | variable = "kms:GrantIsForAWSResource"
378 | values = ["true"]
379 | }
380 |
381 | dynamic "condition" {
382 | for_each = var.route53_dnssec_sources
383 |
384 | content {
385 | test = "StringEquals"
386 | variable = "aws:SourceAccount"
387 | values = try(condition.value.account_ids, [local.account_id])
388 | }
389 | }
390 |
391 | dynamic "condition" {
392 | for_each = var.route53_dnssec_sources
393 |
394 | content {
395 | test = "ArnLike"
396 | variable = "aws:SourceArn"
397 | values = [try(condition.value.hosted_zone_arn, "arn:${local.partition}:route53:::hostedzone/*")]
398 | }
399 | }
400 | }
401 | }
402 |
403 | dynamic "statement" {
404 | for_each = var.key_statements
405 |
406 | content {
407 | sid = try(statement.value.sid, null)
408 | actions = try(statement.value.actions, null)
409 | not_actions = try(statement.value.not_actions, null)
410 | effect = try(statement.value.effect, null)
411 | resources = try(statement.value.resources, null)
412 | not_resources = try(statement.value.not_resources, null)
413 |
414 | dynamic "principals" {
415 | for_each = try(statement.value.principals, [])
416 |
417 | content {
418 | type = principals.value.type
419 | identifiers = principals.value.identifiers
420 | }
421 | }
422 |
423 | dynamic "not_principals" {
424 | for_each = try(statement.value.not_principals, [])
425 |
426 | content {
427 | type = not_principals.value.type
428 | identifiers = not_principals.value.identifiers
429 | }
430 | }
431 |
432 | dynamic "condition" {
433 | for_each = try(statement.value.conditions, [])
434 |
435 | content {
436 | test = condition.value.test
437 | values = condition.value.values
438 | variable = condition.value.variable
439 | }
440 | }
441 | }
442 | }
443 | }
444 |
445 | ################################################################################
446 | # Alias
447 | ################################################################################
448 |
449 | locals {
450 | aliases = { for k, v in toset(var.aliases) : k => { name = v } }
451 | }
452 |
453 | resource "aws_kms_alias" "this" {
454 | for_each = { for k, v in merge(local.aliases, var.computed_aliases) : k => v if var.create }
455 |
456 | name = var.aliases_use_name_prefix ? null : "alias/${each.value.name}"
457 | name_prefix = var.aliases_use_name_prefix ? "alias/${each.value.name}-" : null
458 | target_key_id = try(aws_kms_key.this[0].key_id, aws_kms_external_key.this[0].id, aws_kms_replica_key.this[0].key_id, aws_kms_replica_external_key.this[0].key_id)
459 | }
460 |
461 | ################################################################################
462 | # Grant
463 | ################################################################################
464 |
465 | resource "aws_kms_grant" "this" {
466 | for_each = { for k, v in var.grants : k => v if var.create }
467 |
468 | name = try(each.value.name, each.key)
469 | key_id = try(aws_kms_key.this[0].key_id, aws_kms_external_key.this[0].id, aws_kms_replica_key.this[0].key_id, aws_kms_replica_external_key.this[0].key_id)
470 | grantee_principal = each.value.grantee_principal
471 | operations = each.value.operations
472 |
473 | dynamic "constraints" {
474 | for_each = length(lookup(each.value, "constraints", {})) == 0 ? [] : [each.value.constraints]
475 |
476 | content {
477 | encryption_context_equals = try(constraints.value.encryption_context_equals, null)
478 | encryption_context_subset = try(constraints.value.encryption_context_subset, null)
479 | }
480 | }
481 |
482 | retiring_principal = try(each.value.retiring_principal, null)
483 | grant_creation_tokens = try(each.value.grant_creation_tokens, null)
484 | retire_on_delete = try(each.value.retire_on_delete, null)
485 | }
486 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Key
3 | ################################################################################
4 |
5 | output "key_arn" {
6 | description = "The Amazon Resource Name (ARN) of the key"
7 | value = try(aws_kms_key.this[0].arn, aws_kms_external_key.this[0].arn, aws_kms_replica_key.this[0].arn, aws_kms_replica_external_key.this[0].arn, null)
8 | }
9 |
10 | output "key_id" {
11 | description = "The globally unique identifier for the key"
12 | value = try(aws_kms_key.this[0].key_id, aws_kms_external_key.this[0].id, aws_kms_replica_key.this[0].key_id, aws_kms_replica_external_key.this[0].key_id, null)
13 | }
14 |
15 | output "key_policy" {
16 | description = "The IAM resource policy set on the key"
17 | value = try(aws_kms_key.this[0].policy, aws_kms_external_key.this[0].policy, aws_kms_replica_key.this[0].policy, aws_kms_replica_external_key.this[0].policy, null)
18 | }
19 |
20 | output "external_key_expiration_model" {
21 | description = "Whether the key material expires. Empty when pending key material import, otherwise `KEY_MATERIAL_EXPIRES` or `KEY_MATERIAL_DOES_NOT_EXPIRE`"
22 | value = try(aws_kms_external_key.this[0].expiration_model, aws_kms_replica_external_key.this[0].expiration_model, null)
23 | }
24 |
25 | output "external_key_state" {
26 | description = "The state of the CMK"
27 | value = try(aws_kms_external_key.this[0].key_state, aws_kms_replica_external_key.this[0].key_state, null)
28 | }
29 |
30 | output "external_key_usage" {
31 | description = "The cryptographic operations for which you can use the CMK"
32 | value = try(aws_kms_external_key.this[0].key_usage, aws_kms_replica_external_key.this[0].key_usage, null)
33 | }
34 |
35 | ################################################################################
36 | # Alias
37 | ################################################################################
38 |
39 | output "aliases" {
40 | description = "A map of aliases created and their attributes"
41 | value = aws_kms_alias.this
42 | }
43 |
44 | ################################################################################
45 | # Grant
46 | ################################################################################
47 |
48 | output "grants" {
49 | description = "A map of grants created and their attributes"
50 | value = aws_kms_grant.this
51 | sensitive = true
52 | }
53 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | variable "create" {
2 | description = "Determines whether resources will be created (affects all resources)"
3 | type = bool
4 | default = true
5 | }
6 |
7 | variable "tags" {
8 | description = "A map of tags to add to all resources"
9 | type = map(string)
10 | default = {}
11 | }
12 |
13 | ################################################################################
14 | # Key
15 | ################################################################################
16 |
17 | variable "create_external" {
18 | description = "Determines whether an external CMK (externally provided material) will be created or a standard CMK (AWS provided material)"
19 | type = bool
20 | default = false
21 | }
22 |
23 | variable "bypass_policy_lockout_safety_check" {
24 | description = "A flag to indicate whether to bypass the key policy lockout safety check. Setting this value to true increases the risk that the KMS key becomes unmanageable"
25 | type = bool
26 | default = null
27 | }
28 |
29 | variable "customer_master_key_spec" {
30 | description = "Specifies whether the key contains a symmetric key or an asymmetric key pair and the encryption algorithms or signing algorithms that the key supports. Valid values: `SYMMETRIC_DEFAULT`, `RSA_2048`, `RSA_3072`, `RSA_4096`, `HMAC_256`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`. Defaults to `SYMMETRIC_DEFAULT`"
31 | type = string
32 | default = null
33 | }
34 |
35 | variable "custom_key_store_id" {
36 | description = "ID of the KMS Custom Key Store where the key will be stored instead of KMS (eg CloudHSM)."
37 | type = string
38 | default = null
39 | }
40 |
41 | variable "deletion_window_in_days" {
42 | description = "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. If you do not specify a value, it defaults to `30`"
43 | type = number
44 | default = null
45 | }
46 |
47 | variable "description" {
48 | description = "The description of the key as viewed in AWS console"
49 | type = string
50 | default = null
51 | }
52 |
53 | variable "enable_key_rotation" {
54 | description = "Specifies whether key rotation is enabled. Defaults to `true`"
55 | type = bool
56 | default = true
57 | }
58 |
59 | variable "is_enabled" {
60 | description = "Specifies whether the key is enabled. Defaults to `true`"
61 | type = bool
62 | default = null
63 | }
64 |
65 | variable "key_material_base64" {
66 | description = "Base64 encoded 256-bit symmetric encryption key material to import. The CMK is permanently associated with this key material. External key only"
67 | type = string
68 | default = null
69 | }
70 |
71 | variable "key_usage" {
72 | description = "Specifies the intended use of the key. Valid values: `ENCRYPT_DECRYPT` or `SIGN_VERIFY`. Defaults to `ENCRYPT_DECRYPT`"
73 | type = string
74 | default = null
75 | }
76 |
77 | variable "multi_region" {
78 | description = "Indicates whether the KMS key is a multi-Region (`true`) or regional (`false`) key. Defaults to `false`"
79 | type = bool
80 | default = false
81 | }
82 |
83 | variable "policy" {
84 | description = "A valid policy JSON document. Although this is a key policy, not an IAM policy, an `aws_iam_policy_document`, in the form that designates a principal, can be used"
85 | type = string
86 | default = null
87 | }
88 |
89 | variable "valid_to" {
90 | description = "Time at which the imported key material expires. When the key material expires, AWS KMS deletes the key material and the CMK becomes unusable. If not specified, key material does not expire"
91 | type = string
92 | default = null
93 | }
94 |
95 | variable "enable_default_policy" {
96 | description = "Specifies whether to enable the default key policy. Defaults to `true`"
97 | type = bool
98 | default = true
99 | }
100 |
101 | variable "key_owners" {
102 | description = "A list of IAM ARNs for those who will have full key permissions (`kms:*`)"
103 | type = list(string)
104 | default = []
105 | }
106 |
107 | variable "key_administrators" {
108 | description = "A list of IAM ARNs for [key administrators](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators)"
109 | type = list(string)
110 | default = []
111 | }
112 |
113 | variable "key_users" {
114 | description = "A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users)"
115 | type = list(string)
116 | default = []
117 | }
118 |
119 | variable "key_service_users" {
120 | description = "A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration)"
121 | type = list(string)
122 | default = []
123 | }
124 |
125 | variable "key_service_roles_for_autoscaling" {
126 | description = "A list of IAM ARNs for [AWSServiceRoleForAutoScaling roles](https://docs.aws.amazon.com/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html#policy-example-cmk-access)"
127 | type = list(string)
128 | default = []
129 | }
130 |
131 | variable "key_symmetric_encryption_users" {
132 | description = "A list of IAM ARNs for [key symmetric encryption users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto)"
133 | type = list(string)
134 | default = []
135 | }
136 |
137 | variable "key_hmac_users" {
138 | description = "A list of IAM ARNs for [key HMAC users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto)"
139 | type = list(string)
140 | default = []
141 | }
142 |
143 | variable "key_asymmetric_public_encryption_users" {
144 | description = "A list of IAM ARNs for [key asymmetric public encryption users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto)"
145 | type = list(string)
146 | default = []
147 | }
148 |
149 | variable "key_asymmetric_sign_verify_users" {
150 | description = "A list of IAM ARNs for [key asymmetric sign and verify users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-users-crypto)"
151 | type = list(string)
152 | default = []
153 | }
154 |
155 | variable "key_statements" {
156 | description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage"
157 | type = any
158 | default = {}
159 | }
160 |
161 | variable "source_policy_documents" {
162 | description = "List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s"
163 | type = list(string)
164 | default = []
165 | }
166 |
167 | variable "override_policy_documents" {
168 | description = "List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid`"
169 | type = list(string)
170 | default = []
171 | }
172 |
173 | variable "enable_route53_dnssec" {
174 | description = "Determines whether the KMS policy used for Route53 DNSSEC signing is enabled"
175 | type = bool
176 | default = false
177 | }
178 |
179 | variable "route53_dnssec_sources" {
180 | description = "A list of maps containing `account_ids` and Route53 `hosted_zone_arn` that will be allowed to sign DNSSEC records"
181 | type = list(any)
182 | default = []
183 | }
184 |
185 | variable "rotation_period_in_days" {
186 | description = "Custom period of time between each rotation date. Must be a number between 90 and 2560 (inclusive)"
187 | type = number
188 | default = null
189 | }
190 |
191 | ################################################################################
192 | # Replica Key
193 | ################################################################################
194 |
195 | variable "create_replica" {
196 | description = "Determines whether a replica standard CMK will be created (AWS provided material)"
197 | type = bool
198 | default = false
199 | }
200 |
201 | variable "primary_key_arn" {
202 | description = "The primary key arn of a multi-region replica key"
203 | type = string
204 | default = null
205 | }
206 |
207 | ################################################################################
208 | # Replica External Key
209 | ################################################################################
210 |
211 | variable "create_replica_external" {
212 | description = "Determines whether a replica external CMK will be created (externally provided material)"
213 | type = bool
214 | default = false
215 | }
216 |
217 | variable "primary_external_key_arn" {
218 | description = "The primary external key arn of a multi-region replica external key"
219 | type = string
220 | default = null
221 | }
222 |
223 | ################################################################################
224 | # Alias
225 | ################################################################################
226 |
227 | variable "aliases" {
228 | description = "A list of aliases to create. Note - due to the use of `toset()`, values must be static strings and not computed values"
229 | type = list(string)
230 | default = []
231 | }
232 |
233 | variable "computed_aliases" {
234 | description = "A map of aliases to create. Values provided via the `name` key of the map can be computed from upstream resources"
235 | type = any
236 | default = {}
237 | }
238 |
239 | variable "aliases_use_name_prefix" {
240 | description = "Determines whether the alias name is used as a prefix"
241 | type = bool
242 | default = false
243 | }
244 |
245 | ################################################################################
246 | # Grant
247 | ################################################################################
248 |
249 | variable "grants" {
250 | description = "A map of grant definitions to create"
251 | type = any
252 | default = {}
253 | }
254 |
--------------------------------------------------------------------------------
/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.3"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 5.49"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/wrappers/README.md:
--------------------------------------------------------------------------------
1 | # Wrapper for the root module
2 |
3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
4 |
5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
6 |
7 | This wrapper does not implement any extra functionality.
8 |
9 | ## Usage with Terragrunt
10 |
11 | `terragrunt.hcl`:
12 |
13 | ```hcl
14 | terraform {
15 | source = "tfr:///terraform-aws-modules/kms/aws//wrappers"
16 | # Alternative source:
17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-kms.git//wrappers?ref=master"
18 | }
19 |
20 | inputs = {
21 | defaults = { # Default values
22 | create = true
23 | tags = {
24 | Terraform = "true"
25 | Environment = "dev"
26 | }
27 | }
28 |
29 | items = {
30 | my-item = {
31 | # omitted... can be any argument supported by the module
32 | }
33 | my-second-item = {
34 | # omitted... can be any argument supported by the module
35 | }
36 | # omitted...
37 | }
38 | }
39 | ```
40 |
41 | ## Usage with Terraform
42 |
43 | ```hcl
44 | module "wrapper" {
45 | source = "terraform-aws-modules/kms/aws//wrappers"
46 |
47 | defaults = { # Default values
48 | create = true
49 | tags = {
50 | Terraform = "true"
51 | Environment = "dev"
52 | }
53 | }
54 |
55 | items = {
56 | my-item = {
57 | # omitted... can be any argument supported by the module
58 | }
59 | my-second-item = {
60 | # omitted... can be any argument supported by the module
61 | }
62 | # omitted...
63 | }
64 | }
65 | ```
66 |
67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer
68 |
69 | `eu-west-1/s3-buckets/terragrunt.hcl`:
70 |
71 | ```hcl
72 | terraform {
73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74 | # Alternative source:
75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76 | }
77 |
78 | inputs = {
79 | defaults = {
80 | force_destroy = true
81 |
82 | attach_elb_log_delivery_policy = true
83 | attach_lb_log_delivery_policy = true
84 | attach_deny_insecure_transport_policy = true
85 | attach_require_latest_tls_policy = true
86 | }
87 |
88 | items = {
89 | bucket1 = {
90 | bucket = "my-random-bucket-1"
91 | }
92 | bucket2 = {
93 | bucket = "my-random-bucket-2"
94 | tags = {
95 | Secure = "probably"
96 | }
97 | }
98 | }
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/wrappers/main.tf:
--------------------------------------------------------------------------------
1 | module "wrapper" {
2 | source = "../"
3 |
4 | for_each = var.items
5 |
6 | aliases = try(each.value.aliases, var.defaults.aliases, [])
7 | aliases_use_name_prefix = try(each.value.aliases_use_name_prefix, var.defaults.aliases_use_name_prefix, false)
8 | bypass_policy_lockout_safety_check = try(each.value.bypass_policy_lockout_safety_check, var.defaults.bypass_policy_lockout_safety_check, null)
9 | computed_aliases = try(each.value.computed_aliases, var.defaults.computed_aliases, {})
10 | create = try(each.value.create, var.defaults.create, true)
11 | create_external = try(each.value.create_external, var.defaults.create_external, false)
12 | create_replica = try(each.value.create_replica, var.defaults.create_replica, false)
13 | create_replica_external = try(each.value.create_replica_external, var.defaults.create_replica_external, false)
14 | custom_key_store_id = try(each.value.custom_key_store_id, var.defaults.custom_key_store_id, null)
15 | customer_master_key_spec = try(each.value.customer_master_key_spec, var.defaults.customer_master_key_spec, null)
16 | deletion_window_in_days = try(each.value.deletion_window_in_days, var.defaults.deletion_window_in_days, null)
17 | description = try(each.value.description, var.defaults.description, null)
18 | enable_default_policy = try(each.value.enable_default_policy, var.defaults.enable_default_policy, true)
19 | enable_key_rotation = try(each.value.enable_key_rotation, var.defaults.enable_key_rotation, true)
20 | enable_route53_dnssec = try(each.value.enable_route53_dnssec, var.defaults.enable_route53_dnssec, false)
21 | grants = try(each.value.grants, var.defaults.grants, {})
22 | is_enabled = try(each.value.is_enabled, var.defaults.is_enabled, null)
23 | key_administrators = try(each.value.key_administrators, var.defaults.key_administrators, [])
24 | key_asymmetric_public_encryption_users = try(each.value.key_asymmetric_public_encryption_users, var.defaults.key_asymmetric_public_encryption_users, [])
25 | key_asymmetric_sign_verify_users = try(each.value.key_asymmetric_sign_verify_users, var.defaults.key_asymmetric_sign_verify_users, [])
26 | key_hmac_users = try(each.value.key_hmac_users, var.defaults.key_hmac_users, [])
27 | key_material_base64 = try(each.value.key_material_base64, var.defaults.key_material_base64, null)
28 | key_owners = try(each.value.key_owners, var.defaults.key_owners, [])
29 | key_service_roles_for_autoscaling = try(each.value.key_service_roles_for_autoscaling, var.defaults.key_service_roles_for_autoscaling, [])
30 | key_service_users = try(each.value.key_service_users, var.defaults.key_service_users, [])
31 | key_statements = try(each.value.key_statements, var.defaults.key_statements, {})
32 | key_symmetric_encryption_users = try(each.value.key_symmetric_encryption_users, var.defaults.key_symmetric_encryption_users, [])
33 | key_usage = try(each.value.key_usage, var.defaults.key_usage, null)
34 | key_users = try(each.value.key_users, var.defaults.key_users, [])
35 | multi_region = try(each.value.multi_region, var.defaults.multi_region, false)
36 | override_policy_documents = try(each.value.override_policy_documents, var.defaults.override_policy_documents, [])
37 | policy = try(each.value.policy, var.defaults.policy, null)
38 | primary_external_key_arn = try(each.value.primary_external_key_arn, var.defaults.primary_external_key_arn, null)
39 | primary_key_arn = try(each.value.primary_key_arn, var.defaults.primary_key_arn, null)
40 | rotation_period_in_days = try(each.value.rotation_period_in_days, var.defaults.rotation_period_in_days, null)
41 | route53_dnssec_sources = try(each.value.route53_dnssec_sources, var.defaults.route53_dnssec_sources, [])
42 | source_policy_documents = try(each.value.source_policy_documents, var.defaults.source_policy_documents, [])
43 | tags = try(each.value.tags, var.defaults.tags, {})
44 | valid_to = try(each.value.valid_to, var.defaults.valid_to, null)
45 | }
46 |
--------------------------------------------------------------------------------
/wrappers/outputs.tf:
--------------------------------------------------------------------------------
1 | output "wrapper" {
2 | description = "Map of outputs of a wrapper."
3 | value = module.wrapper
4 | sensitive = true # At least one sensitive module output (grants) found (requires Terraform 0.14+)
5 | }
6 |
--------------------------------------------------------------------------------
/wrappers/variables.tf:
--------------------------------------------------------------------------------
1 | variable "defaults" {
2 | description = "Map of default values which will be used for each item."
3 | type = any
4 | default = {}
5 | }
6 |
7 | variable "items" {
8 | description = "Maps of items to create a wrapper from. Values are passed through to the module."
9 | type = any
10 | default = {}
11 | }
12 |
--------------------------------------------------------------------------------
/wrappers/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.3"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 5.49"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------