terraform-aws-modules Route53

repository·master·Indexed 41 days ago

https://github.com/terraform-aws-modules/terraform-aws-route53

A collection of Terraform modules for managing AWS Route53 resources, including public and private hosted zones, DNS records, Resolver endpoints (inbound and outbound), delegation sets, and Resolver Firewall Rule Groups. Requires Terraform >= 1.5.7 and AWS provider >= 6.28.

Tokens
14.1K
Snippets
25
Records
43
Agent score
94%

What's inside terraform-aws-route53

  1. How the module wrapper pattern works

    master

    The wrapper pattern is a structural implementation designed to bypass the limitations of native Terraform for_each in certain workflows (like Terragrunt) where managing many individual files is cumbersome.

    It works by accepting a map of items. The wrapper iterates over this map to instantiate the root module multiple times. It uses a defaults map to inject common configuration into every instance, allowing you to keep your items definitions concise by only specifying unique or overriding attributes.

  2. Avoid disruptive diffs with ignore_vpc

    master

    When using aws_route53_zone_association resources, changing VPC associations can cause disruptive diffs. Set ignore_vpc = true to prevent the module from attempting to manage or change VPC associations after they are created.

    Warning: Changing this value is a destructive action. If you need to change it later, you should be prepared to use Terraform state move commands or blocks.

  3. Use managed domain lists in firewall rules

    master

    Currently, there is no data source available to automatically pull managed domain list IDs. To use a managed domain list within a rule, you must manually provide the domain_list_id (e.g., rslvr-fdl-fad18de921a64bfa) in your rule configuration.

    # Example of referencing a managed domain list ID manually
    block_managed_domain_list = {
      priority       = 135
      action         = "BLOCK"
      block_response = "NODATA"
      domain_list_id = "rslvr-fdl-fad18de921a64bfa"
    }
  4. Use the module wrapper pattern with Terragrunt

    master

    The wrappers directory provides a pattern for managing multiple instances of the root module within a single configuration. This is particularly useful in Terragrunt when you want to manage several resources without creating a separate terragrunt.hcl file for every single instance.

    To use it, set the source to the wrappers path and provide two main input maps:

    1. defaults: A map of arguments applied to every item.
    2. items: A map where each key represents a unique instance, and the value is a map of arguments specific to that instance. Any argument supported by the root module can be used within these maps.
    terraform {
      source = "tfr:///terraform-aws-modules/route53/aws//wrappers"
    }
    
    inputs = {
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # arguments supported by the root module
        }
        my-second-item = {
          # arguments supported by the root module
        }
      }
    }
  5. Configure an Inbound Resolver Endpoint

    master

    An Inbound Resolver Endpoint allows Route 53 to forward DNS queries from your network or another VPC to the DNS service for a VPC. This module creates the endpoint along with a security group and rules for port 53 (TCP/UDP).

    To configure an inbound endpoint, set direction = "INBOUND" and provide the ip_address list containing the subnet_ids where the endpoint should reside. You should also define security_group_ingress_rules to allow DNS traffic from your source networks.

    module "resolver_endpoint" {
      source = "terraform-aws-modules/route53/aws//modules/resolver-endpoint"
    
      name = "example-inbound"
      direction = "INBOUND"
      type      = "IPV4"
      protocols = ["Do53", "DoH"]
    
      ip_address = [
        {
          subnet_id = "subnet-abcde012"
        },
        {
          subnet_id = "subnet-bcde012a"
        }
      ]
    
      # Security group
      vpc_id = "vpc-1234556abcdef"
      security_group_ingress_rules = {
        one = {
          cidr_ipv4 = "10.0.0.0/20"
          description = "Allow inbound DNS queries from first subnet"
        }
        two = {
          cidr_ipv4 = "10.0.16.0/20"
          description = "Allow inbound DNS queries from second subnet"
        }
      }
      security_group_egress_rules = {
        one = {
          cidr_ipv4 = "10.0.0.0/20"
          description = "Allow outbound DNS responses to first subnet"
        }
        two = {
          cidr_ipv4 = "10.0.16.0/20"
          description = "Allow outbound DNS responses to second subnet"
        }
      }
    
      tags = {
        Environment = "example"
        Project     = "terraform-aws-route53"
      }
    }
  6. Implement Cross Account Route53 Private Hosted Zone Association

    master

    To associate a Route53 Private Hosted Zone in one AWS account with a VPC in a different AWS account (or different region), you must follow a two-step process involving different permissions:

    1. Authorization (Zone Owner Account): The account that owns the Route53 zone must authorize the association. This is handled inside the module via the aws_route53_vpc_association_authorization resource.
    2. Association (VPC Owner Account): The account that owns the VPC must perform the actual association. This is handled outside the module using the aws_route53_zone_association resource.

    This example configuration demonstrates creating:

    • A Route53 Private Hosted Zone with an associated VPC in the same account.
    • A VPC in a different AWS account associated to the Private Hosted Zone.
    • A VPC in a different AWS account and different region associated to the Private Hosted Zone.
    # Note: The actual implementation requires configuring providers for both accounts
    # and using the aws_route53_zone_association resource in the VPC account.
  7. Configure Cross Account Zone Association

    master

    To associate a Route53 zone with a VPC in a different AWS account, you must handle two distinct steps:

    1. Authorization (Inside Module): The account owning the zone must authorize the VPC association. This is handled within the module using the vpc_association_authorizations argument.
    2. Association (Outside Module): The account owning the VPC must perform the actual association using the aws_route53_zone_association resource. This resource is not included in the module.

    Managing the ignore_vpc variable

    To avoid disruptive diffs when managing associations, use the ignore_vpc variable. Note that changing this value requires a state move because Terraform cannot use variables in lifecycle blocks.

    Moving from ignore_vpc = false to true:

    terraform state mv 'module.zone.aws_route53_zone.this[0]' 'module.zone.aws_route53_zone.ignore_vpc[0]'

    Moving from ignore_vpc = true to false:

    terraform state mv 'module.zone.aws_route53_zone.ignore_vpc[0]' 'module.zone.aws_route53_zone.this[0]'

    Alternatively, use a moved block in your HCL configuration.

    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"
      }
    }
  8. Configure the AWS Route53 Resolver Firewall Rule Group module

    master

    This module automates the creation of an AWS Route53 Resolver Firewall Rule Group, including associated RAM resource associations for cross-account sharing, resolver firewall domain lists, and individual firewall rules.

    To use the module, provide a name and a rules map. The rules map allows you to define various types of rules such as standard domain blocks, domain overrides, or rules that reference existing managed domain lists.

    module "resolver_firewall_rule_group" {
      source = "terraform-aws-modules/route53/aws//modules/resolver-firewall-rule-group"
    
      name   = "example"
    
      rules = {
        block = {
          name           = "blockit"
          priority       = 110
          action         = "BLOCK"
          block_response = "NODATA"
          domains        = ["google.com."]
    
          tags = { rule = true }
        }
        block_override = {
          priority                = 120
          action                  = "BLOCK"
          block_response          = "OVERRIDE"
          block_override_dns_type = "CNAME"
          block_override_domain   = "example.com"
          block_override_ttl      = 1
          domains                 = ["microsoft.com."]
        }
        allow = {
          priority = 130
          action   = "ALLOW"
          domains  = ["amazon.com.", "amazonaws.com."]
        }
      }
    
      tags = {
        Environment = "example"
        Project     = "terraform-aws-route53"
      }
    }
  9. Use the delegation-sets wrapper with Terraform

    master

    You can use the delegation-sets wrapper directly in Terraform modules to manage multiple instances of the underlying module using a single module block. This implements a pattern for managing multiple copies of a module where native for_each might not be feasible.

    Configure the wrapper using the defaults and items arguments.

    module "wrapper" {
      source = "terraform-aws-modules/route53/aws//wrappers/delegation-sets"
    
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # any argument supported by the delegation-sets module
        }
        my-second-item = {
          # any argument supported by the delegation-sets module
        }
      }
    }
  10. Use the delegation-sets wrapper with Terragrunt

    master

    The delegation-sets wrapper allows you to manage multiple instances of the modules/delegation-sets module within a single Terragrunt configuration file. This is useful when you want to avoid duplicating terragrunt.hcl files for every instance of the module.

    To use it, set the source to tfr:///terraform-aws-modules/route53/aws//wrappers/delegation-sets and provide configuration via defaults and items in the inputs block.

    terraform {
      source = "tfr:///terraform-aws-modules/route53/aws//wrappers/delegation-sets"
    }
    
    inputs = {
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # any argument supported by the delegation-sets module
        }
        my-second-item = {
          # any argument supported by the delegation-sets module
        }
      }
    }
  11. Configure an Outbound Resolver Endpoint with Rules and Associations

    master

    An Outbound Resolver Endpoint forwards DNS queries from the DNS service for a VPC to your network or another VPC. This module supports creating Resolver Rules (e.g., FORWARD or SYSTEM) and associating them with specific VPCs.

    To configure an outbound endpoint, set direction = "OUTBOUND". Use the rules map to define your DNS forwarding logic. For FORWARD rules, you must provide target_ip and a vpc_id within the rule object to create the association.

    Key configuration for rules:

    • domain_name: The domain to which the rule applies.
    • rule_type: Either FORWARD or SYSTEM.
    • target_ip: A list of IP addresses to forward queries to (required for FORWARD).
    • vpc_id: The VPC to associate the rule with (required for FORWARD).
    module "resolver_endpoint" {
      source = "terraform-aws-modules/route53/aws//modules/resolver-endpoint"
    
      name = "example-inbound"
      direction = "OUTBOUND"
      type      = "IPV4"
      protocols = ["Do53", "DoH"]
    
      ip_address = [
        {
          subnet_id = "subnet-abcde012"
        },
        {
          subnet_id = "subnet-bcde012a"
        }
      ]
    
      # Security group
      vpc_id = "vpc-1234556abcdef"
      security_group_ingress_rules = {
        one = {
          cidr_ipv4 = "10.0.0.0/20"
          description = "Allow inbound DNS queries from first subnet"
        }
        two = {
          cidr_ipv4 = "10.0.16.0/20"
          description = "Allow inbound DNS queries from second subnet"
        }
      }
      security_group_egress_rules = {
        one = {
          cidr_ipv4 = "10.0.0.0/20"
          description = "Allow outbound DNS responses to first subnet"
        }
        two = {
          cidr_ipv4 = "10.0.16.0/20"
          description = "Allow outbound DNS responses to second subnet"
        }
      }
    
      # Resolver Rule(s) & Association(s)
      rules = {
        ex-forward = {
          domain_name = "example.com."
          rule_type   = "FORWARD"
          target_ip = [{
            ip = "123.45.67.89"
          }]
          # Association
          vpc_id = "vpc-1234556abcdef"
        }
        ex-system = {
          domain_name = "system.com."
          rule_type   = "SYSTEM"
        }
      }
    
      tags = {
        Environment = "example"
        Project     = "terraform-aws-route53"
      }
    }