Skip to content

Adds ipv6 support with user-specified prefixes #218

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

Closed
wants to merge 6 commits into from
Closed
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
65 changes: 55 additions & 10 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ resource "aws_internet_gateway" "this" {
tags = "${merge(map("Name", format("%s", var.name)), var.tags, var.igw_tags)}"
}

resource "aws_egress_only_internet_gateway" "this" {
count = "${var.enable_ipv6 && length(var.database_subnets) + length(var.private_subnets) > 0 ? 1 : 0}"

vpc_id = "${aws_vpc.this.id}"
}

################
# Publiс routes
################
Expand All @@ -92,6 +98,14 @@ resource "aws_route" "public_internet_gateway" {
}
}

resource "aws_route" "public_internet_gateway_ipv6" {
count = "${var.enable_ipv6 && length(var.public_subnets) > 0 ? 1 : 0}"

route_table_id = "${aws_route_table.public.id}"
destination_ipv6_cidr_block = "::/0"
gateway_id = "${aws_internet_gateway.this.id}"
}

#################
# Private routes
# There are so many routing tables as the largest amount of subnets of each type (really?)
Expand Down Expand Up @@ -144,6 +158,14 @@ resource "aws_route" "database_nat_gateway" {
}
}

resource "aws_route" "database_ipv6_egress" {
count = "${var.enable_ipv6 ? length(var.database_subnets) : 0}"

route_table_id = "${element(aws_route_table.database.*.id, count.index)}"
destination_ipv6_cidr_block = "::/0"
egress_only_gateway_id = "${element(aws_egress_only_internet_gateway.this.*.id, 0)}"
}

#################
# Redshift routes
#################
Expand Down Expand Up @@ -183,10 +205,14 @@ resource "aws_route_table" "intra" {
resource "aws_subnet" "public" {
count = "${var.create_vpc && length(var.public_subnets) > 0 && (!var.one_nat_gateway_per_az || length(var.public_subnets) >= length(var.azs)) ? length(var.public_subnets) : 0}"

vpc_id = "${local.vpc_id}"
cidr_block = "${element(concat(var.public_subnets, list("")), count.index)}"
availability_zone = "${element(var.azs, count.index)}"
map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
vpc_id = "${local.vpc_id}"
cidr_block = "${element(concat(var.public_subnets, list("")), count.index)}"
availability_zone = "${element(var.azs, count.index)}"
map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
assign_ipv6_address_on_creation = "${var.assign_ipv6_address_on_creation}"

# TODO: Does not unset, need null support or the like see: Terraform 0.12
ipv6_cidr_block = "${var.enable_ipv6 && length(var.public_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this.ipv6_cidr_block, 8, element(concat(var.public_subnet_ipv6_prefixes, list("0")), count.index)) : ""}"

tags = "${merge(map("Name", format("%s-${var.public_subnet_suffix}-%s", var.name, element(var.azs, count.index))), var.tags, var.public_subnet_tags)}"
}
Expand All @@ -197,9 +223,13 @@ resource "aws_subnet" "public" {
resource "aws_subnet" "private" {
count = "${var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0}"

vpc_id = "${local.vpc_id}"
cidr_block = "${var.private_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}"
vpc_id = "${local.vpc_id}"
cidr_block = "${var.private_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}"
assign_ipv6_address_on_creation = "${var.assign_ipv6_address_on_creation}"

# TODO: Does not unset, need null support or the like see: Terraform 0.12
ipv6_cidr_block = "${var.enable_ipv6 && length(var.private_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this.ipv6_cidr_block, 8, element(coalescelist(var.private_subnet_ipv6_prefixes, list("0")), count.index)) : ""}"

tags = "${merge(map("Name", format("%s-${var.private_subnet_suffix}-%s", var.name, element(var.azs, count.index))), var.tags, var.private_subnet_tags)}"
}
Expand All @@ -210,9 +240,13 @@ resource "aws_subnet" "private" {
resource "aws_subnet" "database" {
count = "${var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0}"

vpc_id = "${local.vpc_id}"
cidr_block = "${var.database_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}"
vpc_id = "${local.vpc_id}"
cidr_block = "${var.database_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}"
assign_ipv6_address_on_creation = "${var.assign_ipv6_address_on_creation}"

# TODO: Does not unset, need null support or the like see: Terraform 0.12
ipv6_cidr_block = "${var.enable_ipv6 && length(var.database_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this.ipv6_cidr_block, 8, element(concat(var.database_subnet_ipv6_prefixes, list("0")), count.index)) : ""}"

tags = "${merge(map("Name", format("%s-${var.database_subnet_suffix}-%s", var.name, element(var.azs, count.index))), var.tags, var.database_subnet_tags)}"
}
Expand Down Expand Up @@ -281,6 +315,9 @@ resource "aws_subnet" "intra" {
cidr_block = "${var.intra_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}"

# TODO: Does not unset, need null support or the like see: Terraform 0.12
ipv6_cidr_block = "${var.enable_ipv6 && length(var.intra_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this.ipv6_cidr_block, 8, element(concat(var.intra_subnet_ipv6_prefixes, list("0")), count.index)) : ""}"

tags = "${merge(map("Name", format("%s-intra-%s", var.name, element(var.azs, count.index))), var.tags, var.intra_subnet_tags)}"
}

Expand Down Expand Up @@ -330,6 +367,14 @@ resource "aws_route" "private_nat_gateway" {
}
}

resource "aws_route" "private_ipv6_egress" {
count = "${var.enable_ipv6 ? length(var.private_subnets) : 0}"

route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
destination_ipv6_cidr_block = "::/0"
egress_only_gateway_id = "${aws_egress_only_internet_gateway.this.id}"
}

######################
# VPC Endpoint for S3
######################
Expand Down
43 changes: 34 additions & 9 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ output "vpc_main_route_table_id" {
value = "${element(concat(aws_vpc.this.*.main_route_table_id, list("")), 0)}"
}

//output "vpc_ipv6_association_id" {
// description = "The association ID for the IPv6 CIDR block"
// value = "${element(concat(aws_vpc.this.*.ipv6_association_id, list("")), 0)}"
//}
//
//output "vpc_ipv6_cidr_block" {
// description = "The IPv6 CIDR block"
// value = "${element(concat(aws_vpc.this.*.ipv6_cidr_block, list("")), 0)}"
//}
output "vpc_ipv6_association_id" {
description = "The association ID for the IPv6 CIDR block"
value = "${element(concat(aws_vpc.this.*.ipv6_association_id, list("")), 0)}"
}

output "vpc_ipv6_cidr_block" {
description = "The IPv6 CIDR block"
value = "${element(concat(aws_vpc.this.*.ipv6_cidr_block, list("")), 0)}"
}

output "vpc_secondary_cidr_blocks" {
description = "List of secondary CIDR blocks of the VPC"
Expand Down Expand Up @@ -344,3 +344,28 @@ output "azs" {
description = "A list of availability zones specified as argument to this module"
value = "${var.azs}"
}

output "ipv6_egress_only_igw_id" {
description = "The ID of the egress only Internet Gateway"
value = "${element(concat(aws_egress_only_internet_gateway.this.*.id, list("")), 0)}"
}

output "public_subnets_ipv6_cidr_blocks" {
description = "List of ipv6 cidr_blocks of public subnets in an ipv6 enabled VPC"
value = ["${aws_subnet.public.*.ipv6_cidr_block}"]
}

output "private_subnets_ipv6_cidr_blocks" {
description = "List of ipv6 cidr_blocks of private subnets in an ipv6 enabled VPC"
value = ["${aws_subnet.private.*.ipv6_cidr_block}"]
}

output "database_subnets_ipv6_cidr_blocks" {
description = "List of ipv6 cidr_blocks of database subnets in an ipv6 enabled VPC"
value = ["${aws_subnet.database.*.ipv6_cidr_block}"]
}

output "intra_subnets_ipv6_cidr_blocks" {
description = "List of ipv6 cidr_blocks of intra subnets in an ipv6 enabled VPC"
value = ["${aws_subnet.intra.*.ipv6_cidr_block}"]
}
34 changes: 34 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,40 @@ variable "assign_generated_ipv6_cidr_block" {
default = false

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 remove this variable and set this assign_generated_ipv6_cidr_block = "${var.enable_ipv6}"?

Choose a reason for hiding this comment

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

Ah.. now I see that you actually mentioned this in the PR description..

Copy link
Author

Choose a reason for hiding this comment

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

Yup, I didn't want to remove the option until I had a chance to hear how you wanted to handle it. I wanted to remove the assign_generated_ipv6_cidr_block variable entirely and just set have the new variable name be enable_ipv6. Alternatively, keeping the assign name and making it actually set up the ipv6 cidr associations. Do you have any thoughts on how you'd like it to be handled?

}

variable "enable_ipv6" {
description = "Assigns ipv6 subnets and routes"
default = false
}

variable "private_subnet_ipv6_prefixes" {
description = "Assigns ipv6 subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding ipv4 subnet list"
default = []
type = "list"
}

variable "public_subnet_ipv6_prefixes" {
description = "Assigns ipv6 subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding ipv4 subnet list"
default = []
type = "list"
}

variable "database_subnet_ipv6_prefixes" {
description = "Assigns ipv6 subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding ipv4 subnet list"
default = []
type = "list"
}

variable "intra_subnet_ipv6_prefixes" {
description = "Assigns ipv6 subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding ipv4 subnet list"
default = []
type = "list"
}

variable "assign_ipv6_address_on_creation" {
description = "Assign ipv6 address on subnet, must be disabled to change ipv6 cidrs. This is the ipv6 equivalent of map_public_ip_on_launch"
default = false
}

variable "secondary_cidr_blocks" {
description = "List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool"
default = []
Expand Down