diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..ce1a5e0 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,45 @@ +# Migration to v1.0.0 + +## New Features + +With v1.0.0 we have tried to follow a more consistent pattern in +module design. + +- Use of the `context` provided by the [terraform-null-label](https://github.com/cloudposse/terraform-null-label) module. +- Ability to process hosted zones from other modules easier. + +## Breaking changes in v1.0.0 + +Releases prior to v1.0.0 of this module attempted to maintain compatibility, so required no code changes were needed. +With v1.0.0 in order to address reported issues changes to the code +were necessary that did not allow for upgrade without code changes. If you are unable to afford a break in functionality during upgrade lock +version to an earlier compatible version. + +### Behavior changes + +- Previously, the `aws_route53_key_signing_key` and `random_string` +resources used an index based on the hosted zone ID as passed in by the `zone_ids` variable. This caused an issue where the values were +not known until apply affecting plan execution. + +- Previously, the `aws_kms_key` and `ams_key_alias` resources were +handled internally. These are now handled with an external module +which will destroy the old resources upon apply. + +- Previously, prior to Terraform 1.0 `provider` blocks were necessary +inside external modules when requiring change from root module values. This causes issues when executing with newer versions. + +### Input Variable Changes + +- `zone_ids` removed. Use `zones` instead. + +- `zones` added. Internal changes required a new format for input +of zones to assign the KSK to. + +- `deletion_window_in_days` added. To change the deletion window on +key from the previous hard-coded default of 7 days. + +### Output Variable Changes + +- `this_key_arn` deprecated. Use `key_arn` instead. + +- `key_arm` added. Supplies the KMS key ARN setup for Route53 hosted zone KSK. \ No newline at end of file diff --git a/README.md b/README.md index f35fdea..633e58c 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,17 @@ --> -Short -description +Terraform module to provision an AWS Key Management Service (KMS) Customer Managed Key (CMK) +for Route53 DNS to use as a Key-signing Key (KSK) for enabling DNSSEC on a Hosted Zone. + +Provides the ability to instantiate a single KMS key to be used for multiple hosted zones. + +The KSK is setup using a random string. The CMK has an AWS recommended IAM key policy applied +to it and is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required. + +**IMPORTANT:** Route53 requires the KMS key be provisioned in the `us-east-1` region. If including +within a root module configured in another region then a provider alias must be passwd when using this +module. --- @@ -62,7 +71,7 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are ## Introduction -This is an introduction. + ## Security & Compliance [](https://bridgecrew.io/) @@ -98,9 +107,18 @@ the registry shows many of our inputs as required when in fact they are optional The table below correctly indicates which inputs are required. + +### Major Changes (breaking and otherwise) + +With the v1.0.0 release of this module, it has undergone major breaking changes and added +new functionality. Efforts were made to not create these breaking changes but they were +unavailable due to the nature of the issues fixed. Please see the [migration](MIGRATION.md) +document for details. + For a complete example, see [examples/complete](examples/complete). -For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) +For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) +and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). ```hcl @@ -115,19 +133,21 @@ module "label" { } module "example" { - source = "cloudposse/*****/aws" + source = "ugns/route53-dnssec/aws" # Cloud Posse recommends pinning every module to a specific version # version = "x.x.x" - example = "Hello world!" + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } context = module.label.this } ``` -## Quick Start -Here's how to get started... ## Examples @@ -169,14 +189,13 @@ Available targets: | Name | Source | Version | |------|--------|---------| +| [kms\_key](#module\_kms\_key) | cloudposse/kms-key/aws | 0.12.1 | | [this](#module\_this) | cloudposse/label/null | 0.25.0 | ## Resources | Name | Type | |------|------| -| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | | [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -189,6 +208,7 @@ Available targets: | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) The waiting period, specified in number of days.
After the waiting period ends, AWS KMS deletes the KMS key.
If you specify a value, it must be between 7 and 30, inclusive.
Defaults to `7`. | `number` | `7` | no | | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | @@ -204,13 +224,14 @@ Available targets: | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | -| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | +| [zones](#input\_zones) | (Optional) A map of hosted zones with `zone_id` to assign the
KSK to in the format of:
{
"example.com" = {
zone_id = "Z8VLZEXAMPLE"
}
}
Defaults to `{}` which will generate the KMS key and alias but
not assign it to a hosted zone which can be useful for staging. | `map(map(string))` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [key\_arn](#output\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [this\_key\_arn](#output\_this\_key\_arn) | Deprecated: KMS key arn for Route53 DNSSEC CMK | @@ -232,6 +253,8 @@ Check out these related projects. For additional context, refer to some of these links. +- [domain-configure-dnssec](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-configure-dnssec.html) - AWS Route53 Developers Guide: Configuring DNSSEC for a domain +- [dns-configuring-dnssec](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html) - AWS Route53 Developers Guide: Configuring DNSSEC signing in Amazone Route 53 ## Help diff --git a/README.yaml b/README.yaml index 9505be3..33ed47c 100644 --- a/README.yaml +++ b/README.yaml @@ -6,9 +6,6 @@ # Name of this project name: "terraform-aws-route53-dnssec" -# Logo for this project -#logo: docs/logo.png - # License of this project license: "APACHE2" @@ -35,21 +32,44 @@ related: # List any resources helpful for someone to get started. For example, link to the hashicorp documentation or AWS documentation. references: +- name: "domain-configure-dnssec" + description: "AWS Route53 Developers Guide: Configuring DNSSEC for a domain" + url: "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-configure-dnssec.html" +- name: "dns-configuring-dnssec" + description: "AWS Route53 Developers Guide: Configuring DNSSEC signing in Amazone Route 53" + url: "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html" # Short description of this project description: |- - Short - description + Terraform module to provision an AWS Key Management Service (KMS) Customer Managed Key (CMK) + for Route53 DNS to use as a Key-signing Key (KSK) for enabling DNSSEC on a Hosted Zone. + + Provides the ability to instantiate a single KMS key to be used for multiple hosted zones. + + The KSK is setup using a random string. The CMK has an AWS recommended IAM key policy applied + to it and is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required. + + **IMPORTANT:** Route53 requires the KMS key be provisioned in the `us-east-1` region. If including + within a root module configured in another region then a provider alias must be passwd when using this + module. # Introduction to the project -introduction: |- - This is an introduction. +introduction: "" # How to use this module. Should be an easy example to copy and paste. usage: |- + + ### Major Changes (breaking and otherwise) + + With the v1.0.0 release of this module, it has undergone major breaking changes and added + new functionality. Efforts were made to not create these breaking changes but they were + unavailable due to the nature of the issues fixed. Please see the [migration](MIGRATION.md) + document for details. + For a complete example, see [examples/complete](examples/complete). - For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) + For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) + and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). ```hcl @@ -64,12 +84,16 @@ usage: |- } module "example" { - source = "cloudposse/*****/aws" + source = "ugns/route53-dnssec/aws" # Cloud Posse recommends pinning every module to a specific version # version = "x.x.x" - example = "Hello world!" - + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + context = module.label.this } ``` @@ -80,8 +104,8 @@ examples: |- - [`examples/complete`](https://github.com/ugns/terraform-aws-route53-dnssec/tree/main/examples/complete) - complete example of using this module # How to get started quickly -quickstart: |- - Here's how to get started... +# quickstart: |- +# Here's how to get started... # Other files to include in this README from the project folder include: diff --git a/docs/terraform.md b/docs/terraform.md index 618b514..c01f2c9 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -18,14 +18,13 @@ | Name | Source | Version | |------|--------|---------| +| [kms\_key](#module\_kms\_key) | cloudposse/kms-key/aws | 0.12.1 | | [this](#module\_this) | cloudposse/label/null | 0.25.0 | ## Resources | Name | Type | |------|------| -| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource | | [random_string.ksk](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -38,6 +37,7 @@ | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) The waiting period, specified in number of days.
After the waiting period ends, AWS KMS deletes the KMS key.
If you specify a value, it must be between 7 and 30, inclusive.
Defaults to `7`. | `number` | `7` | no | | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | @@ -53,11 +53,12 @@ | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | -| [zone\_ids](#input\_zone\_ids) | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no | +| [zones](#input\_zones) | (Optional) A map of hosted zones with `zone_id` to assign the
KSK to in the format of:
{
"example.com" = {
zone_id = "Z8VLZEXAMPLE"
}
}
Defaults to `{}` which will generate the KMS key and alias but
not assign it to a hosted zone which can be useful for staging. | `map(map(string))` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [this\_key\_arn](#output\_this\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [key\_arn](#output\_key\_arn) | KMS key arn for Route53 DNSSEC CMK | +| [this\_key\_arn](#output\_this\_key\_arn) | Deprecated: KMS key arn for Route53 DNSSEC CMK | diff --git a/examples/complete/fixtures.us-west-1.tfvars b/examples/complete/fixtures.us-west-1.tfvars new file mode 100644 index 0000000..56aea7e --- /dev/null +++ b/examples/complete/fixtures.us-west-1.tfvars @@ -0,0 +1,7 @@ +region = "us-west-1" + +namespace = "eg" + +stage = "test" + +name = "test-ksk" \ No newline at end of file diff --git a/examples/complete/main.tf b/examples/complete/main.tf index e69de29..b307d3e 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -0,0 +1,12 @@ +module "ksk" { + source = "../.." + context = module.this.context + zones = { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + providers = { + aws = aws.use1 + } +} \ No newline at end of file diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index e69de29..e7382a9 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -0,0 +1,4 @@ +output "key_arn" { + description = "KMS key arn for Route53 DNSSEC CMK" + value = module.kms_key.key_arn +} diff --git a/examples/complete/providers.tf b/examples/complete/providers.tf index e70fb2f..08520de 100644 --- a/examples/complete/providers.tf +++ b/examples/complete/providers.tf @@ -1,3 +1,8 @@ provider "aws" { + region = var.region +} + +provider "aws" { + alias = "use1" region = "us-east-1" -} \ No newline at end of file +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index e69de29..2fad651 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -0,0 +1,4 @@ +variable "region" { + type = string + description = "AWS region" +} \ No newline at end of file diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index e69de29..d051642 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 3.0" + # configuration_aliases = [aws.use1] + } + } + + required_version = ">= 0.13" +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 7e4a233..d20d1ef 100644 --- a/variables.tf +++ b/variables.tf @@ -1,12 +1,29 @@ variable "zones" { - description = "A list of Hosted Zone IDs to assign KSK to" + description = <<-EOT + (Optional) A map of hosted zones with `zone_id` to assign the + KSK to in the format of: + ``` + { + "example.com" = { + zone_id = "Z8VLZEXAMPLE" + } + } + ``` + Defaults to `{}` which will generate the KMS key and alias but + not assign it to a hosted zone which can be useful for staging. + EOT type = map(map(string)) default = {} } variable "deletion_window_in_days" { type = number - description = "(optional) describe your variable" + description = <<-EOT + (Optional) The waiting period, specified in number of days. + After the waiting period ends, AWS KMS deletes the KMS key. + If you specify a value, it must be between 7 and 30, inclusive. + Defaults to `7`. + EOT default = 7 }