Skip to content

Commit

Permalink
Add IPv6 support (#317)
Browse files Browse the repository at this point in the history
* IPv6 support

Add variable "enable_ipv6" to allow enabling IPv6 support (resulting in
passing "assign_generated_ipv6_cidr_block" to aws_vpc.

Enabling IPv6 support further results in an Egress-only internet gateway
being provisioned and routing tables of subnets being adjusted.

Additional variables allow to choose the indices out of the /64 subnets
based on the assigned /56 range.

* Add example for IPv6 usage

* Remove redundant parameter assign_generated_ipv6_cidr_block

This is needed exactly when var.enable_ipv6 is true.

* Set subnet ipv6_cidr_block to null if unused

* Be picky about spelling

* Revert unrelated change

* More IPv6 spelling

* Added IPv6 support to VPC module

* Added IPv6 support to VPC module
  • Loading branch information
antonbabenko authored Sep 2, 2019
1 parent 40821bb commit be962ae
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 54 deletions.
28 changes: 26 additions & 2 deletions README.md

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions examples/ipv6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# VPC with IPv6 enabled

Configuration in this directory creates set of VPC resources with IPv6 enabled on VPC and subnets.

## Usage

To run this example you need to execute:

```bash
$ terraform init
$ terraform plan
$ terraform apply
```

Note that this example may create resources which can cost money (AWS Elastic IP, for example). Run `terraform destroy` when you don't need these resources.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Outputs

| Name | Description |
|------|-------------|
| ipv6\_association\_id | The IPv6 CIDR block |
| ipv6\_cidr\_block | The association ID for the IPv6 CIDR block |
| vpc\_id | The ID of the VPC |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
37 changes: 37 additions & 0 deletions examples/ipv6/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
provider "aws" {
region = "eu-west-1"
}

data "aws_availability_zones" "available" {}

module "vpc" {
source = "../.."

name = "ipv6"

cidr = "10.0.0.0/16"

azs = [data.aws_availability_zones.available.names[0], data.aws_availability_zones.available.names[1]]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
database_subnets = ["10.0.103.0/24", "10.0.104.0/24"]

enable_nat_gateway = false

create_database_subnet_route_table = true
create_database_internet_gateway_route = true

enable_ipv6 = true
assign_ipv6_address_on_creation = true

private_subnet_assign_ipv6_address_on_creation = false

public_subnet_ipv6_prefixes = [0, 1]
private_subnet_ipv6_prefixes = [2, 3]
database_subnet_ipv6_prefixes = [4, 5]

tags = {
Owner = "user"
Environment = "dev"
}
}
15 changes: 15 additions & 0 deletions examples/ipv6/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# VPC
output "vpc_id" {
description = "The ID of the VPC"
value = module.vpc.vpc_id
}

output "ipv6_association_id" {
description = "The IPv6 CIDR block"
value = module.vpc.vpc_ipv6_cidr_block
}

output "ipv6_cidr_block" {
description = "The association ID for the IPv6 CIDR block"
value = module.vpc.vpc_ipv6_association_id
}
2 changes: 1 addition & 1 deletion examples/network-acls/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module "vpc" {

private_dedicated_network_acl = true

assign_generated_ipv6_cidr_block = true
enable_ipv6 = true

enable_nat_gateway = false
single_nat_gateway = true
Expand Down
7 changes: 4 additions & 3 deletions examples/secondary-cidr-blocks/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ module "vpc" {
private_subnets = ["10.0.1.0/24", "10.1.2.0/24", "10.2.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.1.102.0/24", "10.2.103.0/24"]

assign_generated_ipv6_cidr_block = true
enable_nat_gateway = true
single_nat_gateway = true
enable_ipv6 = true

enable_nat_gateway = true
single_nat_gateway = true

public_subnet_tags = {
Name = "overridden-name-public"
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-vpc/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module "vpc" {
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

assign_generated_ipv6_cidr_block = true
enable_ipv6 = true

enable_nat_gateway = true
single_nat_gateway = true
Expand Down
92 changes: 72 additions & 20 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ resource "aws_vpc" "this" {
instance_tenancy = var.instance_tenancy
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
assign_generated_ipv6_cidr_block = var.enable_ipv6

tags = merge(
{
Expand Down Expand Up @@ -95,6 +95,12 @@ resource "aws_internet_gateway" "this" {
)
}

resource "aws_egress_only_internet_gateway" "this" {
count = var.create_vpc && var.enable_ipv6 && local.max_subnet_length > 0 ? 1 : 0

vpc_id = local.vpc_id
}

################
# Publiс routes
################
Expand Down Expand Up @@ -124,6 +130,14 @@ resource "aws_route" "public_internet_gateway" {
}
}

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

route_table_id = aws_route_table.public[0].id
destination_ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.this[0].id
}

#################
# Private routes
# There are as many routing tables as the number of NAT gateways
Expand Down Expand Up @@ -193,6 +207,18 @@ resource "aws_route" "database_nat_gateway" {
}
}

resource "aws_route" "database_ipv6_egress" {
count = var.create_vpc && var.enable_ipv6 && var.create_database_subnet_route_table && length(var.database_subnets) > 0 && var.create_database_internet_gateway_route ? 1 : 0

route_table_id = aws_route_table.database[0].id
destination_ipv6_cidr_block = "::/0"
egress_only_gateway_id = aws_egress_only_internet_gateway.this[0].id

timeouts {
create = "5m"
}
}

#################
# Redshift routes
#################
Expand Down Expand Up @@ -250,10 +276,13 @@ resource "aws_route_table" "intra" {
resource "aws_subnet" "public" {
count = var.create_vpc && length(var.public_subnets) > 0 && (false == 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, [""]), 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, [""]), 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.public_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.public_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.public_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.public_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand All @@ -274,9 +303,12 @@ 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.private_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.private_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.private_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.private_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand All @@ -297,9 +329,12 @@ 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.database_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.database_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.database_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.database_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand Down Expand Up @@ -336,9 +371,12 @@ resource "aws_db_subnet_group" "database" {
resource "aws_subnet" "redshift" {
count = var.create_vpc && length(var.redshift_subnets) > 0 ? length(var.redshift_subnets) : 0

vpc_id = local.vpc_id
cidr_block = var.redshift_subnets[count.index]
availability_zone = element(var.azs, count.index)
vpc_id = local.vpc_id
cidr_block = var.redshift_subnets[count.index]
availability_zone = element(var.azs, count.index)
assign_ipv6_address_on_creation = var.redshift_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.redshift_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.redshift_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.redshift_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand Down Expand Up @@ -375,9 +413,12 @@ resource "aws_redshift_subnet_group" "redshift" {
resource "aws_subnet" "elasticache" {
count = var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0

vpc_id = local.vpc_id
cidr_block = var.elasticache_subnets[count.index]
availability_zone = element(var.azs, count.index)
vpc_id = local.vpc_id
cidr_block = var.elasticache_subnets[count.index]
availability_zone = element(var.azs, count.index)
assign_ipv6_address_on_creation = var.elasticache_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.elasticache_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.elasticache_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.elasticache_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand Down Expand Up @@ -406,9 +447,12 @@ resource "aws_elasticache_subnet_group" "elasticache" {
resource "aws_subnet" "intra" {
count = var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0

vpc_id = local.vpc_id
cidr_block = var.intra_subnets[count.index]
availability_zone = element(var.azs, count.index)
vpc_id = local.vpc_id
cidr_block = var.intra_subnets[count.index]
availability_zone = element(var.azs, count.index)
assign_ipv6_address_on_creation = var.intra_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.intra_subnet_assign_ipv6_address_on_creation

ipv6_cidr_block = var.enable_ipv6 && length(var.intra_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.intra_subnet_ipv6_prefixes[count.index]) : null

tags = merge(
{
Expand Down Expand Up @@ -824,6 +868,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 = element(aws_egress_only_internet_gateway.this.*.id, 0)
}

######################
# VPC Endpoint for S3
######################
Expand Down
Loading

0 comments on commit be962ae

Please sign in to comment.