From a4ad35f642d33e9acd2e7af7e80e84e2502edaab Mon Sep 17 00:00:00 2001 From: Mike McGirr Date: Fri, 20 Mar 2020 20:39:51 -0700 Subject: [PATCH 1/2] Add initial support for IPv6 to the vpc module and add the subnet-ipv6 module --- modules/single-port-sg/main.tf | 8 ++++++ modules/subnet-ipv6/README.md | 3 ++ modules/subnet-ipv6/main.tf | 22 ++++++++++++++ modules/subnet-ipv6/output.tf | 25 ++++++++++++++++ modules/subnet-ipv6/variables.tf | 49 ++++++++++++++++++++++++++++++++ modules/subnet-ipv6/versions.tf | 4 +++ modules/subnets/variables.tf | 3 +- modules/vpc/main.tf | 2 ++ modules/vpc/outputs.tf | 7 +++++ modules/vpc/variables.tf | 7 +++++ 10 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 modules/subnet-ipv6/README.md create mode 100644 modules/subnet-ipv6/main.tf create mode 100644 modules/subnet-ipv6/output.tf create mode 100644 modules/subnet-ipv6/variables.tf create mode 100644 modules/subnet-ipv6/versions.tf diff --git a/modules/single-port-sg/main.tf b/modules/single-port-sg/main.tf index 705e3f5f..0da5d12b 100644 --- a/modules/single-port-sg/main.tf +++ b/modules/single-port-sg/main.tf @@ -17,6 +17,12 @@ variable "cidr_blocks" { type = list(string) } +variable "ipv6_cidr_blocks" { + description = "List of IPv6 CIDR block ranges that the SG allows ingress from" + type = list(string) + default = [] +} + variable "description" { description = "Use this string to add a description for the SG rule" type = string @@ -53,6 +59,7 @@ resource "aws_security_group_rule" "tcp_ingress" { to_port = var.port protocol = "tcp" cidr_blocks = var.cidr_blocks + ipv6_cidr_blocks = var.ipv6_cidr_blocks security_group_id = var.security_group_id } @@ -65,5 +72,6 @@ resource "aws_security_group_rule" "udp_ingress" { to_port = var.port protocol = "udp" cidr_blocks = var.cidr_blocks + ipv6_cidr_blocks = var.ipv6_cidr_blocks security_group_id = var.security_group_id } diff --git a/modules/subnet-ipv6/README.md b/modules/subnet-ipv6/README.md new file mode 100644 index 00000000..104ba926 --- /dev/null +++ b/modules/subnet-ipv6/README.md @@ -0,0 +1,3 @@ + ## AWS subnet IPv6 + + Creates a single IPv6 ready subnet diff --git a/modules/subnet-ipv6/main.tf b/modules/subnet-ipv6/main.tf new file mode 100644 index 00000000..13d932aa --- /dev/null +++ b/modules/subnet-ipv6/main.tf @@ -0,0 +1,22 @@ +/** + * ## AWS Subnet IPv6 + * Creates a single IPv6 ready subnet + * + */ + +resource "aws_subnet" "main" { + vpc_id = var.vpc_id + cidr_block = var.cidr_block + ipv6_cidr_block = cidrsubnet(var.vpc_ipv6_cidr_block, var.ipv6_newbits, var.ipv6_netsum) + availability_zone = var.az + + tags = merge( + { + "Name" = "${var.name_prefix}-${var.az}" + }, + var.extra_tags, + ) + + map_public_ip_on_launch = var.public + assign_ipv6_address_on_creation = true +} diff --git a/modules/subnet-ipv6/output.tf b/modules/subnet-ipv6/output.tf new file mode 100644 index 00000000..dc742dac --- /dev/null +++ b/modules/subnet-ipv6/output.tf @@ -0,0 +1,25 @@ +output "id" { + description = "The subnet id" + value = aws_subnet.main.id +} + +output "cidr_block" { + description = "The IPv4 CIDR block" + value = aws_subnet.main.cidr_block +} + +output "ipv6_cidr_block" { + description = "The IPv6 CIDR block" + value = aws_subnet.main.ipv6_cidr_block +} + +output "az" { + value = aws_subnet.main.availability_zone + description = "The availability zones of the subnet" +} + +output "vpc_id" { + description = "ID of the VPC the subnet is in" + value = var.vpc_id +} + diff --git a/modules/subnet-ipv6/variables.tf b/modules/subnet-ipv6/variables.tf new file mode 100644 index 00000000..430adf97 --- /dev/null +++ b/modules/subnet-ipv6/variables.tf @@ -0,0 +1,49 @@ +variable "name_prefix" { + description = "Name to prefix subnets with" + type = string +} + +variable "vpc_id" { + description = "VPC ID where subnets will be created" + type = string +} + +variable "cidr_block" { + description = "The IPv4 CIDR block for the subnet" + type = string +} + +variable "az" { + description = "The Availaiblity Zones to create the subnet in" + type = string +} + +variable "extra_tags" { + default = {} + description = "Extra tags that will be added to aws_subnet resources" + type = map(string) +} + +# default to creating a public subnet +variable "public" { + default = true + description = "Boolean, maps to the map_public_ip_on_launch variable" + type = bool +} + +variable "vpc_ipv6_cidr_block" { + description = "The IPv6 cidr block for the vpc" + type = string +} + +variable "ipv6_newbits" { + description = "The number of additional bits with which to extend the prefix" + type = number + default = 8 +} + +variable "ipv6_netsum" { + description = "a whole number that can be represented as a binary integer with no more than newbits binary digits" + type = number + default = 162 +} diff --git a/modules/subnet-ipv6/versions.tf b/modules/subnet-ipv6/versions.tf new file mode 100644 index 00000000..ac97c6ac --- /dev/null +++ b/modules/subnet-ipv6/versions.tf @@ -0,0 +1,4 @@ + +terraform { + required_version = ">= 0.12" +} diff --git a/modules/subnets/variables.tf b/modules/subnets/variables.tf index 73130302..4277c55d 100644 --- a/modules/subnets/variables.tf +++ b/modules/subnets/variables.tf @@ -28,6 +28,5 @@ variable "extra_tags" { variable "public" { default = true description = "Boolean, maps to the map_public_ip_on_launch variable" - type = string # no boolean type... + type = bool } - diff --git a/modules/vpc/main.tf b/modules/vpc/main.tf index 098b902a..1715ee08 100644 --- a/modules/vpc/main.tf +++ b/modules/vpc/main.tf @@ -16,6 +16,8 @@ resource "aws_vpc" "main" { enable_dns_hostnames = var.enable_dns_hostnames enable_dns_support = var.enable_dns_support + assign_generated_ipv6_cidr_block = var.assign_generated_ipv6_cidr_block + tags = merge( { "Name" = var.name_prefix diff --git a/modules/vpc/outputs.tf b/modules/vpc/outputs.tf index 77a216d3..1a877d73 100644 --- a/modules/vpc/outputs.tf +++ b/modules/vpc/outputs.tf @@ -13,3 +13,10 @@ output "dhcp_options_id" { description = "ID of the DHCP options resource" } +# It would be great if Terraform had an Option or Maybe type +# Otherwise this will output an empty default value if the IPv6 option is not +# set to true +output "ipv6_cidr_block" { + value = (var.assign_generated_ipv6_cidr_block ? aws_vpc.main.ipv6_cidr_block : "") + description = "Optional IPv6 CIDR block output for the VPC" +} diff --git a/modules/vpc/variables.tf b/modules/vpc/variables.tf index 240f6c3c..51dcb6e4 100644 --- a/modules/vpc/variables.tf +++ b/modules/vpc/variables.tf @@ -35,6 +35,13 @@ variable "dns_servers" { default = ["AmazonProvidedDNS"] description = "list of DNS servers for the DHCP options resource" type = list(string) + +} + +variable "assign_generated_ipv6_cidr_block" { + description = "Whether to request an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC" + type = bool + default = false } variable "ntp_servers" { From aedd0c861dbb589ae62c0f89029c21fd82308ef5 Mon Sep 17 00:00:00 2001 From: Mike McGirr Date: Sat, 21 Mar 2020 19:00:27 -0700 Subject: [PATCH 2/2] Add initial IPv6 support to the open-egress-sg and route-public modules --- modules/open-egress-sg/main.tf | 7 +++++++ modules/route-public/main.tf | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/modules/open-egress-sg/main.tf b/modules/open-egress-sg/main.tf index 2ad2b81a..9bd926f6 100644 --- a/modules/open-egress-sg/main.tf +++ b/modules/open-egress-sg/main.tf @@ -18,6 +18,12 @@ variable "cidr_blocks" { type = list(string) } +variable "ipv6_cidr_blocks" { + description = "Allow egress to these IPv6 CIDR blocks" + type = list(string) + default = [] +} + variable "description" { description = "use this string to generate a description for the SG rules" default = "OPEN egress, all ports, all protocols" @@ -32,6 +38,7 @@ resource "aws_security_group_rule" "open_egress" { to_port = "0" protocol = "-1" cidr_blocks = var.cidr_blocks + ipv6_cidr_blocks = var.ipv6_cidr_blocks security_group_id = var.security_group_id } diff --git a/modules/route-public/main.tf b/modules/route-public/main.tf index cfa2bb3a..e4dddfd1 100644 --- a/modules/route-public/main.tf +++ b/modules/route-public/main.tf @@ -41,3 +41,10 @@ resource "aws_route" "public" { depends_on = [aws_route_table.public] } +resource "aws_route" "public6" { + # TODO make this optional or control with count + route_table_id = aws_route_table.public.id + destination_ipv6_cidr_block = "::/0" + gateway_id = aws_internet_gateway.public.id + depends_on = [aws_route_table.public] +}