Terraform module to create AWS Route53 Resolver Rules.
Before you start to forward queries, you must create Resolver outbound endpoints in the connected VPCs. These endpoints provide a path for inbound or outbound queries. To accomplish this you can create the endpoints using the aws_route53_resolver_endpoint resource or use a module like the terraform-aws-route53-endpoint
Check the examples folder for the simple and the complete snippets.
This example creates two rules in a outbound endpoint, using all the parameter expected for building the rules:
# Outbound endpoint using the rhythmictech/terraform-aws-route53-endpoint module
module "r53-outbound" {
  source            = "git::https://github.com/rhythmictech/terraform-aws-route53-endpoint?ref=v0.3.1"
  direction         = "outbound"
  allowed_resolvers = ["192.168.0.0/24"]
  vpc_id            = "vpc-0fffff0123456789"
  ip_addresses      = [
    {
      ip        = "172.30.1.10"
      subnet_id = "subnet-abcd123456789aaaa"
    },
    {
      ip        = "172.30.2.10"
      subnet_id = "subnet-abcd123456789bbbb"
    }
  ]
}
# AWS Route 53 Resolver rules
module "r53-resolver-rules" {
  source               = "git::https://github.com/lgallard/terraform-aws-route53-resolver-rules.git?ref=0.2.0"
  resolver_endpoint_id = module.r53-outbound.endpoint_id
  rules = [
    { rule_name   = "r53r-rule-1"
      domain_name = "bar.foo."
      ram_name    = "ram-r53r-1"
      vpc_ids     = ["vpc-0fffff0123456789"]
      ips         = ["192.168.10.10", "192.168.10.11:54"]
      principals  = ["123456789101", "101987654321"]
    },
    {
      rule_name   = "r53r-rule-2"
      domain_name = "example.com."
      ram_name    = "ram-r53r-2"
      vpc_ids     = ["vpc-0fffff0123456789"]
      ips         = ["192.168.10.10", "192.168.10.11:54"]
      principals  = ["123456789101", "101987654321"]
    }
  ]
}
Note: You can define IP and ports using the IP:PORT syntax, as shown above.
| Name | Description | Type | Default | Required | 
|---|---|---|---|---|
| resolver_endpoint_id | The ID of the outbound resolver endpoint that you want to use to route DNS queries to the IP addresses that you specify using target_ip. | string | 
null | 
yes | 
| rules | List of rules | list | 
[] | 
no | 
| tags | Map of tags to apply to supported resources | map(string) | 
{} | 
no | 
Each rule accept the following parameters:
| Name | Description | Type | Default | Required | 
|---|---|---|---|---|
| domain_name | Domain name to forward requests for | string | null | 
yes | 
| ips | List of IPs and ports to forward DNS requests to. Use IP:PORT syntax, or just the IP | list(string) | [] | 
yes | 
| principals | List of account IDs to share the resolver rule with | list(string) | [] | 
no | 
| ram_name | RAM share name | string | r53-domain_name-rule | 
no | 
| resolver_endpoint_id | Resolver endpoint id | string | null | 
yes | 
| rule_name | Route53 resolver rule name | string | domain_name-rule | 
no | 
| tags | Map of tags to apply to supported resources | map(string) | {} | 
no | 
| vpc_ids | List of VPC ids to associate to the rule | list(string) | [] | 
yes | 
This module includes comprehensive tests using Terratest. The test suite covers:
- Basic resolver rule creation and validation
 - Multiple resolver rules with different configurations
 - VPC association functionality
 - RAM resource sharing for cross-account scenarios
 - Custom DNS port configurations
 - Resource tagging
 - Input validation and edge cases
 
To run the tests locally:
cd test
go mod tidy
go test -v -timeout 30mFor more details on the testing framework and how to run specific tests, see the test documentation.
- ✅ Basic resolver rule creation
 - ✅ Multiple resolver rules
 - ✅ VPC associations
 - ✅ RAM resource sharing
 - ✅ Custom DNS ports
 - ✅ Resource tagging
 - ✅ Input validation and error cases
 - ✅ Module outputs
 - ✅ Edge cases and boundary conditions
 
This repository uses pre-commit hooks to ensure code quality and DNS/networking-specific validation. The hooks include:
- Terraform formatting (
terraform fmt) - Terraform validation (
terraform validate) - Terraform documentation (auto-generated)
 - TFLint for advanced Terraform linting
 - TFSec for security scanning
 - DNS domain validation (ensures FQDN format with trailing dots)
 - VPC ID format validation
 - IP address format validation
 - YAML/JSON validation
 - Secret detection
 - File formatting (trailing whitespace, end-of-file fixes)
 
- 
Install pre-commit:
pip install pre-commit
 - 
Install the hooks:
pre-commit install
 - 
Run hooks manually (optional):
# Run on all files pre-commit run --all-files # Run on specific files pre-commit run --files main.tf variables.tf
 
The pre-commit hooks include custom validations for Route53 resolver rules:
- Domain Names: Must be fully qualified (end with a dot), e.g., 
"example.com." - VPC IDs: Must follow AWS format, e.g., 
"vpc-12345678" - IP Addresses: Must use valid IPv4 format, optionally with ports, e.g., 
"192.168.1.1:53" 
The pre-commit setup includes several configuration files:
.pre-commit-config.yaml- Main pre-commit configuration.tflint.hcl- TFLint rules for Terraform linting.tfsec.yml- TFSec security scanning configuration.terraform-docs.yml- Terraform documentation generation.secrets.baseline- Baseline for secret detection
These hooks run automatically on every commit and help maintain code quality, security, and DNS/networking best practices.
Before you start to forward queries, you must create Resolver outbound endpoints in the connected VPCs. These endpoints provide a path for inbound or outbound queries. To accomplish this you can create the endpoints using the aws_route53_resolver_endpoint resource or use a module like the terraform-aws-route53-endpoint
Check the examples folder for the simple and the complete snippets.
This example creates two rules in a outbound endpoint, using all the parameter expected for building the rules:
# Outbound endpoint using the rhythmictech/terraform-aws-route53-endpoint module
module "r53-outbound" {
  source            = "git::https://github.com/rhythmictech/terraform-aws-route53-endpoint?ref=v0.3.1"
  direction         = "outbound"
  allowed_resolvers = ["192.168.0.0/24"]
  vpc_id            = "vpc-0fffff0123456789"
  ip_addresses      = [
    {
      ip        = "172.30.1.10"
      subnet_id = "subnet-abcd123456789aaaa"
    },
    {
      ip        = "172.30.2.10"
      subnet_id = "subnet-abcd123456789bbbb"
    }
  ]
}
# AWS Route 53 Resolver rules
module "r53-resolver-rules" {
  source               = "git::https://github.com/lgallard/terraform-aws-route53-resolver-rules.git?ref=0.2.0"
  resolver_endpoint_id = module.r53-outbound.endpoint_id
  rules = [
    { rule_name   = "r53r-rule-1"
      domain_name = "bar.foo."
      ram_name    = "ram-r53r-1"
      vpc_ids     = ["vpc-0fffff0123456789"]
      ips         = ["192.168.10.10", "192.168.10.11:54"]
      principals  = ["123456789101", "101987654321"]
    },
    {
      rule_name   = "r53r-rule-2"
      domain_name = "example.com."
      ram_name    = "ram-r53r-2"
      vpc_ids     = ["vpc-0fffff0123456789"]
      ips         = ["192.168.10.10", "192.168.10.11:54"]
      principals  = ["123456789101", "101987654321"]
    }
  ]
}Note: You can define IP and ports using the IP:PORT syntax, as shown above.
| Name | Version | 
|---|---|
| terraform | >= 1.0 | 
| aws | >= 4.0 | 
| Name | Version | 
|---|---|
| aws | 6.6.0 | 
No modules.
| Name | Type | 
|---|---|
| aws_ram_principal_association.endpoint_ram_principal | resource | 
| aws_ram_resource_association.endpoint_ram_resource | resource | 
| aws_ram_resource_share.endpoint_share | resource | 
| aws_route53_resolver_rule.r | resource | 
| aws_route53_resolver_rule_association.ra | resource | 
| Name | Description | Type | Default | Required | 
|---|---|---|---|---|
| resolver_endpoint_id | The ID of the outbound resolver endpoint that you want to use to route DNS queries to the IP addresses specified in target_ip | string | 
null | 
no | 
| rules | List of rules | list(any) | 
[] | 
no | 
| tags | Map of tags to apply to supported resources. Each tag is a key-value pair stored as a map of strings. | map(string) | 
{} | 
no | 
| Name | Description | 
|---|---|
| resolver_rules | Resolver rules | 
