Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Route53 resolver module #1

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog

All notable changes to this project will automatically be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# terraform-aws-mcaf-route53-resolver

Terraform module to create Route53 resolver. This will be useful when creating the Route53 Resolver either inbound or outbound.

Please note that this module does not cover the Resolver query logging.
Comment on lines +3 to +5

Choose a reason for hiding this comment

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

This Terraform module provisions an AWS Route 53 Resolver Endpoint for inbound or outbound DNS resolution.

Choose a reason for hiding this comment

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

Query logging is not a core functionality so no need to mention that it's not there imo


IMPORTANT: We do not pin modules to versions in our examples. We highly recommend that in your code you pin the version to the exact version you are using so that your infrastructure remains stable.

## Terraform AWS Route53 Resolver Module

Choose a reason for hiding this comment

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

Suggested change
## Terraform AWS Route53 Resolver Module


<!-- BEGIN_TF_DOCS -->

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement_terraform) | >= 1.9 |
| <a name="requirement_aws"></a> [aws](#requirement_aws) | >= 5.32 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider_aws) | >= 5.32 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="security_group"></a> [security_group](#security_group) | schubergphilis/mcaf-security-group/aws | 0.1.0 |

## Resources

| Name | Type |
|------|------|
| [aws_route53_resolver_endpoint.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_resolver_endpoint) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="create_security_group"></a> [create_security_group](#input_create_security_group) | Whether to create Security Groups for Route53 Resolver Endpoints | `bool` | `true` | no |
| <a name="direction"></a> [direction](#input_direction) | The resolver endpoint flow direction | `string` | `"INBOUND"` | no |
| <a name="ip_address"></a> [ip_address](#input_ip_address) | A list of IP addresses and subnets where Route53 resolver endpoints will be deployed | `list(object({ ip = optional(string), subnet_id = string }))` | `[]` | no |
| <a name="name"></a> [name](#input_name) | The resolver endpoint name | `string` | n/a | yes |
| <a name="protocols"></a> [protocols](#input_protocols) | The resolver endpoint protocols | `list(string)` | `[]` | no |
| <a name="security_group_description"></a> [security_group_description](#input_security_group_description) | Security group description for DNS resolver | `string` | `null` | no |
| <a name="security_group_egress_cidr_blocks"></a> [security_group_egress_cidr_blocks](#input_security_group_egress_cidr_blocks) | CIDR blocks allowed in security group egress rules | `string` | `"0.0.0.0/0"` | no |
| <a name="security_group_ids"></a> [security_group_ids](#input_security_group_ids) | A list of security group IDs | `list(string)` | `[]` | no |
| <a name="security_group_ingress_cidr_blocks"></a> [security_group_ingress_cidr_blocks](#input_security_group_ingress_cidr_blocks) | CIDR blocks allowed in security group ingress rules | `string` | `""` | no |
| <a name="security_group_name"></a> [security_group_name](#input_security_group_name) | The name of the security group | `string` | `null` | no |
| <a name="security_group_name_prefix"></a> [security_group_name_prefix](#input_security_group_name_prefix) | Prefix for the security group name | `string` | `null` | no |
| <a name="subnet_ids"></a> [subnet_ids](#input_subnet_ids) | List of subnets where Route53 resolver endpoints will be deployed | `list(string)` | `[]` | no |
| <a name="tags"></a> [tags](#input_tags) | A map of tags for the Route53 resolver endpoint | `map(string)` | `{}` | no |
| <a name="type"></a> [type](#input_type) | The resolver endpoint IP type | `string` | `"IPV4"` | no |
| <a name="vpc_id"></a> [vpc_id](#input_vpc_id) | The VPC ID for all the Route53 Resolver Endpoints | `string` | `""` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="route53_resolver_endpoint_id"></a> [route53_resolver_endpoint_id](#output_route53_resolver_endpoint_id) | The ID of the Resolver Endpoint |
| <a name="route53_resolver_endpoint_arn"></a> [route53_resolver_endpoint_arn](#output_route53_resolver_endpoint_arn) | The ARN of the Resolver Endpoint |
| <a name="route53_resolver_endpoint_host_vpc_id"></a> [route53_resolver_endpoint_host_vpc_id](#output_route53_resolver_endpoint_host_vpc_id) | The VPC ID used by the Resolver Endpoint |
| <a name="route53_resolver_endpoint_security_group_ids"></a> [route53_resolver_endpoint_security_group_ids](#output_route53_resolver_endpoint_security_group_ids) | Security Group IDs mapped to Resolver Endpoint |
| <a name="route53_resolver_endpoint_ip_addresses"></a> [route53_resolver_endpoint_ip_addresses](#output_route53_resolver_endpoint_ip_addresses) | Resolver Endpoint IP Addresses |

<!-- END_TF_DOCS -->

## Licensing

100% Open Source and licensed under the Apache License Version 2.0. See [LICENSE](https://github.com/schubergphilis/terraform-aws-mcaf-user/blob/master/LICENSE) for full details.

Choose a reason for hiding this comment

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

Suggested change
100% Open Source and licensed under the Apache License Version 2.0. See [LICENSE](https://github.com/schubergphilis/terraform-aws-mcaf-user/blob/master/LICENSE) for full details.
100% Open Source and licensed under the Apache License Version 2.0. See [LICENSE](https://github.com/schubergphilis/terraform-aws-mcaf-route53-resolver/blob/master/LICENSE) for full details.

44 changes: 44 additions & 0 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
provider "aws" {
region = "eu-west-1"
}

# vpc
module "vpc" {
source = "github.com/schubergphilis/terraform-aws-mcaf-vpc?ref=v1.22.1"

name = "test"
cidr_block = "192.168.0.0/24"
availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
public_subnet_bits = 28
private_subnet_bits = 28

tags = {
environment = "test"
}
}

# Example to create the Route53 Inbound Resolver.
module "inbound_resolver_endpoints" {
source = "../.."

direction = "INBOUND"
name = "resolver-endpoints-example"
protocols = ["Do53", "DoH"]
security_group_ingress_cidr_blocks = module.vpc.cidr_block
security_group_name_prefix = "resolver-endpoints-example-"
subnet_ids = module.vpc.private_subnet_ids
vpc_id = module.vpc.id
}

# Example to create the Route53 Outbound Resolver
module "outbound_resolver_endpoints" {
source = "../.."

direction = "OUTBOUND"
name = "resolver-endpoints-example"
protocols = ["Do53", "DoH"]
security_group_ingress_cidr_blocks = module.vpc.cidr_block
security_group_name_prefix = "resolver-endpoints-example-"
subnet_ids = module.vpc.private_subnet_ids
vpc_id = module.vpc.id
}
10 changes: 10 additions & 0 deletions examples/basic/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.9"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.32"
}
}
}
55 changes: 55 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
locals {
security_group_ids = var.create_security_group ? [module.security_group[0].id] : var.security_group_ids
subnet_ids = [for subnet in var.subnet_ids : { subnet_id = subnet }]
}

resource "aws_route53_resolver_endpoint" "default" {
direction = var.direction
name = var.name
protocols = var.protocols
resolver_endpoint_type = var.type
security_group_ids = local.security_group_ids
tags = var.tags

dynamic "ip_address" {
for_each = length(var.ip_address) == 0 ? local.subnet_ids : var.ip_address

content {
ip = lookup(ip_address.value, "ip", null)
subnet_id = ip_address.value.subnet_id
}
}
}

module "security_group" {
count = var.create_security_group ? 1 : 0

source = "schubergphilis/mcaf-security-group/aws"
version = "0.1.0"

Choose a reason for hiding this comment

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

Suggested change
version = "0.1.0"
version = "~> 0.1.0"


description = var.security_group_description
name = var.security_group_name
name_prefix = var.security_group_name_prefix
tags = var.tags
vpc_id = var.vpc_id

Choose a reason for hiding this comment

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

https://github.com/schubergphilis/terraform-aws-mcaf-lambda/blob/master/main.tf#L58

if you add a data source for this then you don't need the vpc_id variable anymore


egress_rules = {
for protocol in toset(["tcp", "udp"]) : "${protocol}-53" => {
description = "Allow DNS for outside world"
ip_protocol = protocol
from_port = 53
to_port = 53
cidr_ipv4 = var.security_group_egress_cidr_blocks
}
}

ingress_rules = {
for protocol in toset(["tcp", "udp"]) : "${protocol}-53" => {
description = "Allow DNS on port 53 for defined CIDR blocks"
ip_protocol = protocol
from_port = 53
to_port = 53
cidr_ipv4 = var.security_group_ingress_cidr_blocks
}
}
}
24 changes: 24 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
output "route53_resolver_endpoint_id" {
description = "The ID of the Resolver Endpoint"
value = aws_route53_resolver_endpoint.default.id
}

output "route53_resolver_endpoint_arn" {
description = "The ARN of the Resolver Endpoint"
value = aws_route53_resolver_endpoint.default.arn
}

output "route53_resolver_endpoint_host_vpc_id" {
description = "The VPC ID used by the Resolver Endpoint"
value = aws_route53_resolver_endpoint.default.host_vpc_id
}

output "route53_resolver_endpoint_security_group_ids" {
description = "Security Group IDs mapped to Resolver Endpoint"
value = aws_route53_resolver_endpoint.default.security_group_ids
}

output "route53_resolver_endpoint_ip_addresses" {
description = "Resolver Endpoint IP Addresses"
value = aws_route53_resolver_endpoint.default.ip_address
}
10 changes: 10 additions & 0 deletions terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.9"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.32"
}
}
}
97 changes: 97 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
variable "create_security_group" {
type = bool
default = true
description = "Whether to create Security Groups for Route53 Resolver Endpoints"
}

variable "direction" {
type = string
default = "INBOUND"
description = "The resolver endpoint flow direction"
}

variable "ip_address" {
type = list(object({
ip = optional(string)
subnet_id = string
}))
default = []
description = "A list of IP addresses and subnets where Route53 resolver endpoints will be deployed"
}

variable "name" {
type = string
description = "The resolver endpoint name"
}

variable "protocols" {
type = list(string)
default = []

Choose a reason for hiding this comment

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

Would it make sense to default to ["Do53", "DoH"] ?

description = "The resolver endpoint protocols"
}

variable "security_group_description" {
type = string
default = null
description = "This security group is created to allow port 53 for DNS resolver"

Choose a reason for hiding this comment

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

Suggested change
description = "This security group is created to allow port 53 for DNS resolver"
description = "Route53 Resolver Endpoint Security Group, allows port 53 for DNS resolving"

}

variable "security_group_egress_cidr_blocks" {
type = string
default = "0.0.0.0/0"
description = "A list of CIDR blocks to allow on security group egress rules"

Choose a reason for hiding this comment

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

not a list but a string

Choose a reason for hiding this comment

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

Discussion point: take security group module out.. if not then we need to support multiple cidr_blocks and add looping

nullable = false
}

variable "security_group_ids" {
type = list(string)
default = []
description = "A list of security group IDs"
}

variable "security_group_ingress_cidr_blocks" {
type = string
default = ""
description = "A list of CIDR blocks to allow on security group ingress rules"
}

variable "security_group_name" {
type = string
default = null
description = "The name of the security group"
}

variable "security_group_name_prefix" {
type = string
default = null
description = "The prefix of the security group"
}

variable "subnet_ids" {
type = list(string)
default = []
description = "A list of subnets where Route53 resolver endpoints will be deployed"

validation {
condition = length(var.subnet_ids) == 0 || length(var.ip_address) == 0
error_message = "Either 'subnet_ids' or 'ip_address' can be defined."
}
}

variable "tags" {
type = map(string)
default = {}
description = "A map of tags for the Route53 resolver endpoint"
}

variable "type" {
type = string
default = "IPV4"
description = "The resolver endpoint IP type"
}

variable "vpc_id" {
type = string
default = ""
description = "The VPC ID for all the Route53 Resolver Endpoints"
}
Loading