From ee1808a0cc00d9f46d2d2b49a9d1b470e3b52c80 Mon Sep 17 00:00:00 2001 From: Byungjin Park Date: Mon, 21 Mar 2022 16:46:10 +0900 Subject: [PATCH] Add kms-key module --- .github/labeler.yaml | 2 + .github/labels.yaml | 3 + modules/kms-key/README.md | 72 +++++++++++++++++++ modules/kms-key/main.tf | 54 ++++++++++++++ modules/kms-key/outputs.tf | 65 +++++++++++++++++ modules/kms-key/resource-group.tf | 44 ++++++++++++ modules/kms-key/variables.tf | 112 ++++++++++++++++++++++++++++++ modules/kms-key/versions.tf | 10 +++ 8 files changed, 362 insertions(+) create mode 100644 modules/kms-key/README.md create mode 100644 modules/kms-key/main.tf create mode 100644 modules/kms-key/outputs.tf create mode 100644 modules/kms-key/resource-group.tf create mode 100644 modules/kms-key/variables.tf create mode 100644 modules/kms-key/versions.tf diff --git a/.github/labeler.yaml b/.github/labeler.yaml index 6853dea..11140fd 100644 --- a/.github/labeler.yaml +++ b/.github/labeler.yaml @@ -1,3 +1,5 @@ # Modules +":floppy_disk: kms-key": +- modules/kms-key/**/* ":floppy_disk: secrets-manager-secret": - modules/secrets-manager-secret/**/* diff --git a/.github/labels.yaml b/.github/labels.yaml index 41f4daa..f9d6fc8 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -40,6 +40,9 @@ name: "size/XL" # Modules +- color: "fbca04" + description: "This issue or pull request is related to kms-key module." + name: ":floppy_disk: kms-key" - color: "fbca04" description: "This issue or pull request is related to secrets-manager-secret module." name: ":floppy_disk: secrets-manager-secret" diff --git a/modules/kms-key/README.md b/modules/kms-key/README.md new file mode 100644 index 0000000..e3f3d31 --- /dev/null +++ b/modules/kms-key/README.md @@ -0,0 +1,72 @@ +# kms-key + +This module creates following resources. + +- `aws_kms_key` +- `aws_kms_alias` (optional) +- `aws_kms_grant` (optional) + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.1 | +| [aws](#requirement\_aws) | >= 4.6 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.6.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_resourcegroups_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | (Required) Name of the KMS key. | `string` | n/a | yes | +| [aliases](#input\_aliases) | (Optional) List of display name of the alias. The name must start with the word `alias/`. | `list(string)` | `[]` | no | +| [bypass\_policy\_lockout\_safety\_check](#input\_bypass\_policy\_lockout\_safety\_check) | (Optional) Specifies whether to disable the policy lockout check performed when creating or updating the key's policy. Setting this value to true increases the risk that the CMK becomes unmanageable. For more information, refer to the scenario in the Default Key Policy section in the AWS Key Management Service Developer Guide. | `bool` | `false` | no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) Duration in days after which the key is deleted after destruction of the resource. Valid value is between `7` and `30` days. Defaults to `30`. | `number` | `30` | no | +| [description](#input\_description) | (Optional) The description of the KMS key. | `string` | `""` | no | +| [enabled](#input\_enabled) | (Optional) Indicates whether the key is enabled. | `bool` | `true` | no | +| [key\_rotation\_enabled](#input\_key\_rotation\_enabled) | (Optional) Indicates whether key rotation is enabled. | `bool` | `false` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [multi\_region\_enabled](#input\_multi\_region\_enabled) | (Optional) Indicates whether the key is a multi-Region (true) or regional (false) key. | `bool` | `false` | no | +| [policy](#input\_policy) | (Optional) 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 | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [spec](#input\_spec) | (Optional) 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`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`. Defaults to `SYMMETRIC_DEFAULT`. | `string` | `"SYMMETRIC_DEFAULT"` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [usage](#input\_usage) | (Optional) Specifies the intended use of the key. Valid values are `ENCRYPT_DECRYPT` or `SIGN_VERIFY`. | `string` | `"ENCRYPT_DECRYPT"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [aliases](#output\_aliases) | A collection of aliases of the key. | +| [arn](#output\_arn) | The ARN of the KMS key. | +| [bypass\_policy\_lockout\_safety\_check](#output\_bypass\_policy\_lockout\_safety\_check) | Whether to disable the policy lockout check performed when creating or updating the key's policy. | +| [deletion\_window\_in\_days](#output\_deletion\_window\_in\_days) | Duration in days after which the key is deleted after destruction of the resource. | +| [enabled](#output\_enabled) | Whether the key is enabled. | +| [id](#output\_id) | The ID of the KMS key. | +| [key\_rotation\_enabled](#output\_key\_rotation\_enabled) | Whether the key rotation is enabled. | +| [multi\_region\_enabled](#output\_multi\_region\_enabled) | Whether the key is a multi-region key. | +| [name](#output\_name) | The KMS Key name. | +| [policy](#output\_policy) | The Resource Policy for KMS Key. | +| [spec](#output\_spec) | The specification of KMS key which is the encryption algorithm or signing algorithm. | +| [usage](#output\_usage) | The usage of the KMS key. `ENCRYPT_DECRYPT` or `SIGN_VERIFY`. | + diff --git a/modules/kms-key/main.tf b/modules/kms-key/main.tf new file mode 100644 index 0000000..f9c480e --- /dev/null +++ b/modules/kms-key/main.tf @@ -0,0 +1,54 @@ +locals { + metadata = { + package = "terraform-aws-secret" + version = trimspace(file("${path.module}/../../VERSION")) + module = basename(path.module) + name = var.name + } + module_tags = var.module_tags_enabled ? { + "module.terraform.io/package" = local.metadata.package + "module.terraform.io/version" = local.metadata.version + "module.terraform.io/name" = local.metadata.module + "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" + "module.terraform.io/instance" = local.metadata.name + } : {} +} + + +################################################### +# KMS Resources +################################################### + +resource "aws_kms_key" "this" { + description = var.description + + key_usage = var.usage + customer_master_key_spec = var.spec + + policy = var.policy + bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check + + deletion_window_in_days = var.deletion_window_in_days + + is_enabled = var.enabled + enable_key_rotation = var.key_rotation_enabled + multi_region = var.multi_region_enabled + + tags = merge( + { + "Name" = local.metadata.name + }, + local.module_tags, + var.tags, + ) +} + +# Provides an alias for a KMS customer master key. +# AWS Console enforces 1-to-1 mapping between aliases & keys, +# but API allows you to create as many aliases as the account limits. +resource "aws_kms_alias" "this" { + for_each = toset(var.aliases) + + name = each.key + target_key_id = aws_kms_key.this.key_id +} diff --git a/modules/kms-key/outputs.tf b/modules/kms-key/outputs.tf new file mode 100644 index 0000000..dc8761e --- /dev/null +++ b/modules/kms-key/outputs.tf @@ -0,0 +1,65 @@ +output "arn" { + description = "The ARN of the KMS key." + value = aws_kms_key.this.arn +} + +output "id" { + description = "The ID of the KMS key." + value = aws_kms_key.this.key_id +} + +output "name" { + description = "The KMS Key name." + value = var.name +} + +output "usage" { + description = "The usage of the KMS key. `ENCRYPT_DECRYPT` or `SIGN_VERIFY`." + value = aws_kms_key.this.key_usage +} + +output "spec" { + description = "The specification of KMS key which is the encryption algorithm or signing algorithm." + value = aws_kms_key.this.customer_master_key_spec +} + +output "policy" { + description = "The Resource Policy for KMS Key." + value = aws_kms_key.this.policy +} + +output "bypass_policy_lockout_safety_check" { + description = "Whether to disable the policy lockout check performed when creating or updating the key's policy." + value = aws_kms_key.this.bypass_policy_lockout_safety_check +} + +output "deletion_window_in_days" { + description = "Duration in days after which the key is deleted after destruction of the resource." + value = aws_kms_key.this.deletion_window_in_days +} + +output "enabled" { + description = "Whether the key is enabled." + value = aws_kms_key.this.is_enabled +} + +output "key_rotation_enabled" { + description = "Whether the key rotation is enabled." + value = aws_kms_key.this.enable_key_rotation +} + +output "multi_region_enabled" { + description = "Whether the key is a multi-region key." + value = aws_kms_key.this.multi_region +} + +output "aliases" { + description = "A collection of aliases of the key." + value = { + for alias in aws_kms_alias.this : + alias.name => { + arn = alias.arn + name = alias.name + } + } +} diff --git a/modules/kms-key/resource-group.tf b/modules/kms-key/resource-group.tf new file mode 100644 index 0000000..af108f9 --- /dev/null +++ b/modules/kms-key/resource-group.tf @@ -0,0 +1,44 @@ +locals { + resource_group_name = (var.resource_group_name != "" + ? var.resource_group_name + : join(".", [ + local.metadata.package, + local.metadata.module, + replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), + ]) + ) + resource_group_filters = [ + for key, value in local.module_tags : { + "Key" = key + "Values" = [value] + } + ] + resource_group_query = <<-JSON + { + "ResourceTypeFilters": [ + "AWS::AllSupported" + ], + "TagFilters": ${jsonencode(local.resource_group_filters)} + } + JSON +} + +resource "aws_resourcegroups_group" "this" { + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 + + name = local.resource_group_name + description = var.resource_group_description + + resource_query { + type = "TAG_FILTERS_1_0" + query = local.resource_group_query + } + + tags = merge( + { + "Name" = local.resource_group_name + }, + local.module_tags, + var.tags, + ) +} diff --git a/modules/kms-key/variables.tf b/modules/kms-key/variables.tf new file mode 100644 index 0000000..d54b1ad --- /dev/null +++ b/modules/kms-key/variables.tf @@ -0,0 +1,112 @@ +variable "name" { + description = "(Required) Name of the KMS key." + type = string +} + +variable "description" { + description = "(Optional) The description of the KMS key." + type = string + default = "" +} + +variable "usage" { + description = "(Optional) Specifies the intended use of the key. Valid values are `ENCRYPT_DECRYPT` or `SIGN_VERIFY`." + type = string + default = "ENCRYPT_DECRYPT" + + validation { + condition = contains(["ENCRYPT_DECRYPT", "SIGN_VERIFY"], var.usage) + error_message = "Valid values are `ENCRYPT_DECRYPT` or `SIGN_VERIFY`." + } +} + +variable "spec" { + description = "(Optional) 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`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`. Defaults to `SYMMETRIC_DEFAULT`." + type = string + default = "SYMMETRIC_DEFAULT" +} + +variable "policy" { + description = "(Optional) 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." + type = string + default = null +} + +variable "bypass_policy_lockout_safety_check" { + description = "(Optional) Specifies whether to disable the policy lockout check performed when creating or updating the key's policy. Setting this value to true increases the risk that the CMK becomes unmanageable. For more information, refer to the scenario in the Default Key Policy section in the AWS Key Management Service Developer Guide." + type = bool + default = false +} + +variable "deletion_window_in_days" { + description = "(Optional) Duration in days after which the key is deleted after destruction of the resource. Valid value is between `7` and `30` days. Defaults to `30`." + type = number + default = 30 + + validation { + condition = alltrue([ + var.deletion_window_in_days >= 7, + var.deletion_window_in_days <= 30, + ]) + error_message = "Valid value is between `7` and `30` days." + } +} + +variable "enabled" { + description = "(Optional) Indicates whether the key is enabled." + type = bool + default = true +} + +variable "key_rotation_enabled" { + description = "(Optional) Indicates whether key rotation is enabled." + type = bool + default = false +} + +variable "multi_region_enabled" { + description = "(Optional) Indicates whether the key is a multi-Region (true) or regional (false) key." + type = bool + default = false +} + +variable "aliases" { + description = "(Optional) List of display name of the alias. The name must start with the word ``alias/`." + type = list(string) + default = [] +} + +variable "tags" { + description = "(Optional) A map of tags to add to all resources." + type = map(string) + default = {} +} + +variable "module_tags_enabled" { + description = "(Optional) Whether to create AWS Resource Tags for the module informations." + type = bool + default = true +} + + +################################################### +# Resource Group +################################################### + +variable "resource_group_enabled" { + description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." + type = bool + default = true +} + +variable "resource_group_name" { + description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." + type = string + default = "" +} + +variable "resource_group_description" { + description = "(Optional) The description of Resource Group." + type = string + default = "Managed by Terraform." +} diff --git a/modules/kms-key/versions.tf b/modules/kms-key/versions.tf new file mode 100644 index 0000000..79f1550 --- /dev/null +++ b/modules/kms-key/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.6" + } + } +}