Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,85 @@ module "zone" {
}
```

### Cross Account Zone Association

> [!NOTE]
> Association (`aws_route53_zone_association`) must be performed by the account that owns the VPC.
>
> Association authorization (`aws_route53_vpc_association_authorization`) must be performed by the account that owns the zone.
>
> Hence why the `aws_route53_zone_association` resource is *outside* the scope of the module, but the authorization (`aws_route53_vpc_association_authorization`) is *inside* the scope of the module.

> [!CAUTION]
> Since Terraform does not support variables in the `lifecycle_block`, the `ignore_vpc` variable is used to switch between two resources: `aws_route53_zone.this` and `aws_route53_zone.ignore_vpc`.
> Therefore, if you changes this value after resources have been created, Terraform will attempt to destroy and recreate the Route53 zone which is usually not desired. To avoid this,
> you will need to perform the appropriate state move commands/blocks between the two resources.
>
> Changing from `ignore_vpc = false` to `ignore_vpc = true`:
>
> ```bash
>terraform state mv 'module.zone.aws_route53_zone.this[0]' 'module.zone.aws_route53_zone.ignore_vpc[0]'
> ```
>
> Or using a state block:
>
>```hcl
>moved {
> from = module.zone.aws_route53_zone.this[0]
> to = module.zone.aws_route53_zone.ignore_vpc[0]
>}
> ```
>
> Changing from `ignore_vpc = true` to `ignore_vpc = false`:
>
>```bash
>terraform state mv 'module.zone.aws_route53_zone.ignore_vpc[0]' 'module.zone.aws_route53_zone.this[0]'
> ```
>
> Or using a state block:
>
>```hcl
>moved {
> from = module.zone.aws_route53_zone.ignore_vpc[0]
> to = module.zone.aws_route53_zone.this[0]
>}
> ```
>

```hcl
module "zone" {
source = "terraform-aws-modules/route53/aws"

name = "terraform-aws-modules-example.com"
comment = "Private zone for terraform-aws-modules example"

# Ignore VPC after creation to avoid disruptive diff with associations
ignore_vpc = true
vpc = {
default = {
vpc_id = "vpc-1234556abcdef"
vpc_region = "eu-west-1"
}
}

vpc_association_authorizations = {
external = {
vpc_id = "vpc-987564fedcba"
vpc_region = "eu-west-1"
}
external_region = {
vpc_id = "vpc-1a2b3c4d56e7f8"
vpc_region = "us-east-1"
}
}

tags = {
Environment = "example"
Project = "terraform-aws-route53"
}
}
```

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ignore_vpc should be mentioned/explained here. Maybe more explicit description (as per my previous comment) could be avoided and ignore_vpc could be documented in this section in a better way. Ideally, aws_route53_zone_association docs could be linked for clarification as to why this is needed.

Now feel free to ignore me or rewrite this completely to your liking, but I'm at least going to provide a suggestion:

> [!WARNING]
> 
> Associating the zone using standalone resources causes disruptive diffs on the aws_route53_zone resource.
>
> For this reason the `ignore_vpc` variable is provided to avoid inconsistent plans. Changing the value of this variable is destructive and will cause recreation of the aws_route53_zone resource. 
>
> It is necessary to use terraform state move command/block to switch between the different aws_route53_zone resource to prevent this behaviour.

```hcl
# When changing ignore_vpc to true
moved {
  from = aws_route53_zone.this[0]
  to   = aws_route53_zone.ignore_vpc[0]
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clarified in 300b46b

## Sub-Modules

The following independent sub-modules are available:
Expand All @@ -201,6 +280,7 @@ See the respective module directories for examples and documentation.
## Examples

- [Complete](https://github.com/terraform-aws-modules/terraform-aws-route53/tree/master/examples/complete)
- [Cross Account](https://github.com/terraform-aws-modules/terraform-aws-route53/tree/master/examples/cross-account)

<!-- BEGIN_TF_DOCS -->
## Requirements
Expand Down Expand Up @@ -230,6 +310,7 @@ See the respective module directories for examples and documentation.
| [aws_route53_key_signing_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_key_signing_key) | resource |
| [aws_route53_record.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_vpc_association_authorization.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_vpc_association_authorization) | resource |
| [aws_route53_zone.ignore_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |

Expand All @@ -248,6 +329,7 @@ See the respective module directories for examples and documentation.
| <a name="input_dnssec_kms_key_tags"></a> [dnssec\_kms\_key\_tags](#input\_dnssec\_kms\_key\_tags) | Additional tags to apply to the KMS key created for DNSSEC signing | `map(string)` | `{}` | no |
| <a name="input_enable_dnssec"></a> [enable\_dnssec](#input\_enable\_dnssec) | Whether to enable DNSSEC for the Route53 zone | `bool` | `false` | no |
| <a name="input_force_destroy"></a> [force\_destroy](#input\_force\_destroy) | Whether to destroy all records (possibly managed outside of Terraform) in the zone when destroying the zone | `bool` | `null` | no |
| <a name="input_ignore_vpc"></a> [ignore\_vpc](#input\_ignore\_vpc) | Determines whether to ignore VPC association changes after creation to avoid disruptive diffs when using `aws_route53_zone_association` resource(s). Changing is a destructive action; users should be prepared to use Terraform state move commands/blocks when changing this value | `bool` | `false` | no |
| <a name="input_name"></a> [name](#input\_name) | This is the name of the hosted zone | `string` | `""` | no |
| <a name="input_private_zone"></a> [private\_zone](#input\_private\_zone) | Whether the hosted zone is private. Only applicable when `create_zone = false` | `bool` | `false` | no |
| <a name="input_records"></a> [records](#input\_records) | A map of Route53 records to create in the zone. The key can be used as the subdomain name, or `name` can be used to specify the full name | <pre>map(object({<br/> alias = optional(object({<br/> evaluate_target_health = optional(bool, false)<br/> name = string<br/> zone_id = string<br/> }))<br/> allow_overwrite = optional(bool)<br/> cidr_routing_policy = optional(object({<br/> collection_id = string<br/> location_name = string<br/> }))<br/> failover_routing_policy = optional(object({<br/> type = string<br/> }))<br/> geolocation_routing_policy = optional(object({<br/> continent = optional(string)<br/> country = optional(string)<br/> subdivision = optional(string)<br/> }))<br/> geoproximity_routing_policy = optional(object({<br/> aws_region = optional(string)<br/> bias = optional(number)<br/> coordinates = optional(list(object({<br/> latitude = number<br/> longitude = number<br/> })))<br/> local_zone_group = optional(string)<br/> }))<br/> health_check_id = optional(string)<br/> latency_routing_policy = optional(object({<br/> region = string<br/> }))<br/> multivalue_answer_routing_policy = optional(bool)<br/> name = optional(string)<br/> full_name = optional(string)<br/> records = optional(list(string))<br/> set_identifier = optional(string)<br/> ttl = optional(number)<br/> type = string<br/> weighted_routing_policy = optional(object({<br/> weight = number<br/> }))<br/> timeouts = optional(object({<br/> create = optional(string)<br/> update = optional(string)<br/> delete = optional(string)<br/> }))<br/> }))</pre> | `{}` | no |
Expand Down
1 change: 0 additions & 1 deletion examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

Configuration in this directory creates:


## Usage

To run this example you need to execute:
Expand Down
128 changes: 128 additions & 0 deletions examples/cross-account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Cross Account Route53 Zone Association

Configuration in this directory creates:

- A Route53 Private Hosted Zone w/ associated VPC in one AWS account
- A VPC in another AWS account, associated to the Private Hosted Zone in the first account
- A VPC in another AWS account and region, associated to the Private Hosted Zone in the first account

> [!NOTE]
> Association (`aws_route53_zone_association`) must be performed by the account that owns the VPC.
>
> Association authorization (`aws_route53_vpc_association_authorization`) must be performed by the account that owns the zone.
>
> Hence why the `aws_route53_zone_association` resource is *outside* the scope of the module, but the authorization (`aws_route53_vpc_association_authorization`) is *inside* the scope of the module.

> [!CAUTION]
> Since Terraform does not support variables in the `lifecycle_block`, the `ignore_vpc` variable is used to switch between two resources: `aws_route53_zone.this` and `aws_route53_zone.ignore_vpc`.
> Therefore, if you changes this value after resources have been created, Terraform will attempt to destroy and recreate the Route53 zone which is usually not desired. To avoid this,
> you will need to perform the appropriate state move commands/blocks between the two resources.
>
> Changing from `ignore_vpc = false` to `ignore_vpc = true`:
>
> ```bash
>terraform state mv 'module.zone.aws_route53_zone.this[0]' 'module.zone.aws_route53_zone.ignore_vpc[0]'
> ```
>
> Or using a state block:
>
>```hcl
>moved {
> from = module.zone.aws_route53_zone.this[0]
> to = module.zone.aws_route53_zone.ignore_vpc[0]
>}
> ```
>
> Changing from `ignore_vpc = true` to `ignore_vpc = false`:
>
>```bash
>terraform state mv 'module.zone.aws_route53_zone.ignore_vpc[0]' 'module.zone.aws_route53_zone.this[0]'
> ```
>
> Or using a state block:
>
>```hcl
>moved {
> from = module.zone.aws_route53_zone.ignore_vpc[0]
> to = module.zone.aws_route53_zone.this[0]
>}
> ```
>

## Usage

To run this example you need to execute:

```bash
$ terraform init
$ terraform plan
$ terraform apply
```

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.

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.3 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.3 |
| <a name="provider_aws.external"></a> [aws.external](#provider\_aws.external) | >= 6.3 |
| <a name="provider_aws.external_region"></a> [aws.external\_region](#provider\_aws.external\_region) | >= 6.3 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
| <a name="module_vpc_external"></a> [vpc\_external](#module\_vpc\_external) | terraform-aws-modules/vpc/aws | ~> 6.0 |
| <a name="module_vpc_external_region"></a> [vpc\_external\_region](#module\_vpc\_external\_region) | terraform-aws-modules/vpc/aws | ~> 6.0 |
| <a name="module_zone"></a> [zone](#module\_zone) | ../.. | n/a |

## Resources

| Name | Type |
|------|------|
| [aws_route53_zone_association.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone_association) | resource |
| [aws_route53_zone_association.external_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone_association) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_availability_zones.external_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_external_account_role_arn"></a> [external\_account\_role\_arn](#input\_external\_account\_role\_arn) | The ARN of the role to assume in the external account containing the VPC to be associated to the Route53 private zone | `string` | `"YOU MUST PROVIDE THIS VALUE"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_zone_arn"></a> [zone\_arn](#output\_zone\_arn) | Zone ARN of Route53 zone |
| <a name="output_zone_dnssec_kms_key_arn"></a> [zone\_dnssec\_kms\_key\_arn](#output\_zone\_dnssec\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_zone_dnssec_kms_key_id"></a> [zone\_dnssec\_kms\_key\_id](#output\_zone\_dnssec\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_zone_dnssec_kms_key_policy"></a> [zone\_dnssec\_kms\_key\_policy](#output\_zone\_dnssec\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_zone_dnssec_kms_key_region"></a> [zone\_dnssec\_kms\_key\_region](#output\_zone\_dnssec\_kms\_key\_region) | The region for the key |
| <a name="output_zone_dnssec_signing_key_digest_value"></a> [zone\_dnssec\_signing\_key\_digest\_value](#output\_zone\_dnssec\_signing\_key\_digest\_value) | A cryptographic digest of a DNSKEY resource record (RR). DNSKEY records are used to publish the public key that resolvers can use to verify DNSSEC signatures that are used to secure certain kinds of information provided by the DNS system |
| <a name="output_zone_dnssec_signing_key_dnskey_record"></a> [zone\_dnssec\_signing\_key\_dnskey\_record](#output\_zone\_dnssec\_signing\_key\_dnskey\_record) | A string that represents a DNSKEY record |
| <a name="output_zone_dnssec_signing_key_ds_record"></a> [zone\_dnssec\_signing\_key\_ds\_record](#output\_zone\_dnssec\_signing\_key\_ds\_record) | A string that represents a delegation signer (DS) record |
| <a name="output_zone_dnssec_signing_key_id"></a> [zone\_dnssec\_signing\_key\_id](#output\_zone\_dnssec\_signing\_key\_id) | Route 53 Hosted Zone identifier and KMS Key identifier, separated by a comma (`,`) |
| <a name="output_zone_dnssec_signing_key_public_key"></a> [zone\_dnssec\_signing\_key\_public\_key](#output\_zone\_dnssec\_signing\_key\_public\_key) | The public key, represented as a Base64 encoding, as required by RFC-4034 Page 5 |
| <a name="output_zone_dnssec_signing_key_tag"></a> [zone\_dnssec\_signing\_key\_tag](#output\_zone\_dnssec\_signing\_key\_tag) | An integer used to identify the DNSSEC record for the domain name. The process used to calculate the value is described in RFC-4034 Appendix B |
| <a name="output_zone_id"></a> [zone\_id](#output\_zone\_id) | Zone ID of Route53 zone |
| <a name="output_zone_name"></a> [zone\_name](#output\_zone\_name) | Name of Route53 zone |
| <a name="output_zone_name_servers"></a> [zone\_name\_servers](#output\_zone\_name\_servers) | Name servers of Route53 zone |
| <a name="output_zone_primary_name_server"></a> [zone\_primary\_name\_server](#output\_zone\_primary\_name\_server) | The Route 53 name server that created the SOA record. |
| <a name="output_zone_records"></a> [zone\_records](#output\_zone\_records) | Records created in the Route53 zone |
<!-- END_TF_DOCS -->

## License

Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-ecs/blob/master/LICENSE).
Loading