Skip to content

Commit

Permalink
feat: Module introduction
Browse files Browse the repository at this point in the history
  • Loading branch information
jbouse committed Mar 3, 2021
1 parent dfd0bbc commit 5f1edc6
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Local .terraform directories
**/.terraform/*
**/.terraform.lock.hcl

# .tfstate files
*.tfstate
Expand Down
94 changes: 92 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,92 @@
# terraform-aws-route53-dnssec
Terraform AWS Route53 DNSSEC module
# AWS Route53 DNSSEC Terraform Module

Terraform module which creates an AWS Key Management Service (KMS) Customer
Managed Key (CMK) for Route53 DNS to use as a Key-signing Key (KSK) for
enabling DNSSEC on a Hosted Zone.

KSK is setup using a random string and CMK sets up using a name prefix of
'alias/ksk-'. CMK has an AWS recommended IAM key policy applied to it and
is created as an Asymmetric ECC_NIST_P256/ECDSA_SHA_256 key as required.

## Terraform versions

Current module supports Terraform >= 0.13. Submit pull-requests to `main` branch.

## Usage

```hcl
module "ksk" {
source = "UGNS/route53-dnssec/aws"
version = "0.1.0"
zone_ids = [
"Z2ES7B9AZ6SHAE",
]
tags = {
Name = "my-domain.com"
}
}
```

## Conditional creation

Sometimes you need to create the CMK but conditionally not apply it to any Route53
Hosted Zone. In this instance you can leave `zone_ids` empty and the KMS CMK will
be generated but no KSK will be created and applied to Route53.

```hcl
module "ksk" {
source = "UGNS/route53-dnssec/aws"
# ... omitted
}
```

## Notes

Manual steps will still need to be taken to actually enable DNSSEC for the Route53
Hosted Zone.

* Establish a chain of trust with domain registrar
* Enable DNSSEC signing with the KSK

These steps can not be automated at this time and thus require manual effort to
complete the process. Until both steps are taken DNSSEC will not be protecting
your zone records.

## Requirements

| Name | Version |
|------|---------|
| terraform | >= 0.13 |
| aws | ~> 3.0 |
| random | ~> 3.0 |

## Providers

| Name | Version |
|------|---------|
| aws | ~> 3.0 |
| random | ~> 3.0 |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| tags | A mapping of tags to assign to the resource | `map(string)` | `{}` | no |
| zone\_ids | A list of Hosted Zone IDs to assign KSK to | `list(string)` | `[]` | no |

## Outputs

| Name | Description |
|------|-------------|
| this_key_arn | KMS key ARN for Route53 DNSSEC CMK |

## Authors

Module managed by [Jeremy T. Bouse](https://github.com/jbouse) for [UnderGrid Network Services](https://github.com/UGNS).

## License

Mozilla Public License 2.0. See LICENSE for fulld details.
51 changes: 51 additions & 0 deletions iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
data "aws_caller_identity" "this" {}

data "aws_iam_policy_document" "ksk" {
policy_id = "dnssec-policy"

statement {
sid = "Enable IAM User Permissions"

actions = ["kms:*"]
resources = ["*"]

principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.this.account_id}:root"]
}
}

statement {
sid = "Allow Route 53 DNSSEC Service"

actions = [
"kms:DescribeKey",
"kms:GetPublicKey",
"kms:Sign",
]
resources = ["*"]

principals {
type = "Service"
identifiers = ["dnssec-route53.amazonaws.com"]
}
}

statement {
sid = "Allow Route 53 DNSSEC to CreateGrant"

actions = ["kms:CreateGrant"]
resources = ["*"]

principals {
type = "Service"
identifiers = ["dnssec-route53.amazonaws.com"]
}

condition {
test = "Bool"
variable = "kms:GrantIsForAWSResource"
values = ["true"]
}
}
}
41 changes: 41 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
resource "aws_kms_key" "this" {
provider = aws.use1
customer_master_key_spec = "ECC_NIST_P256"
key_usage = "SIGN_VERIFY"
deletion_window_in_days = 7
description = "Route53 DNSSEC customer managed CMK"
policy = data.aws_iam_policy_document.ksk.json
tags = merge(
var.tags,
{
ManagedBy = "Terraform"
Changed = formatdate("YYYY-MM-DD hh:mm ZZZ", timestamp())
},
)
}

resource "aws_kms_alias" "this" {
provider = aws.use1
name_prefix = "alias/ksk-"
target_key_id = aws_kms_key.this.key_id
}

resource "random_string" "ksk" {
for_each = toset(var.zone_ids)

keepers = {
hosted_zone_id = each.key
key_management_service_arn = aws_kms_key.this.arn
}

length = 32
special = false
}

resource "aws_route53_key_signing_key" "this" {
for_each = toset(var.zone_ids)

hosted_zone_id = random_string.ksk[each.key].keepers.hosted_zone_id
key_management_service_arn = aws_kms_key.this.arn
name = random_string.ksk[each.key].id
}
4 changes: 4 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "this_key_arn" {
description = "KMS key arn for Route53 DNSSEC CMK"
value = aws_kms_key.this.arn
}
4 changes: 4 additions & 0 deletions provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
provider "aws" {
alias = "use1"
region = "us-east-1"
}
11 changes: 11 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "tags" {
type = map(string)
description = "A mapping of tags to assign to the resource"
default = {}
}

variable "zone_ids" {
description = "A list of Hosted Zone IDs to assign KSK to"
type = list(string)
default = []
}
14 changes: 14 additions & 0 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}

required_version = ">= 0.13"
}

0 comments on commit 5f1edc6

Please sign in to comment.