Commit 4fe7745d authored by drewmullen's avatar drewmullen Committed by GitHub

feat: Add IPAM IPv6 support (#718)

Co-authored-by: default avatarBryant Biggs <bryantbiggs@gmail.com>
parent 6e356d2a
...@@ -355,7 +355,7 @@ No modules. ...@@ -355,7 +355,7 @@ No modules.
| <a name="input_amazon_side_asn"></a> [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | `string` | `"64512"` | no | | <a name="input_amazon_side_asn"></a> [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | `string` | `"64512"` | no |
| <a name="input_assign_ipv6_address_on_creation"></a> [assign\_ipv6\_address\_on\_creation](#input\_assign\_ipv6\_address\_on\_creation) | Assign IPv6 address on subnet, must be disabled to change IPv6 CIDRs. This is the IPv6 equivalent of map\_public\_ip\_on\_launch | `bool` | `false` | no | | <a name="input_assign_ipv6_address_on_creation"></a> [assign\_ipv6\_address\_on\_creation](#input\_assign\_ipv6\_address\_on\_creation) | Assign IPv6 address on subnet, must be disabled to change IPv6 CIDRs. This is the IPv6 equivalent of map\_public\_ip\_on\_launch | `bool` | `false` | no |
| <a name="input_azs"></a> [azs](#input\_azs) | A list of availability zones names or ids in the region | `list(string)` | `[]` | no | | <a name="input_azs"></a> [azs](#input\_azs) | A list of availability zones names or ids in the region | `list(string)` | `[]` | no |
| <a name="input_cidr"></a> [cidr](#input\_cidr) | (Optional) The IPv4 CIDR block for the VPC. | `string` | `"0.0.0.0/0"` | no | | <a name="input_cidr"></a> [cidr](#input\_cidr) | (Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id` | `string` | `"0.0.0.0/0"` | no |
| <a name="input_create_database_internet_gateway_route"></a> [create\_database\_internet\_gateway\_route](#input\_create\_database\_internet\_gateway\_route) | Controls if an internet gateway route for public database access should be created | `bool` | `false` | no | | <a name="input_create_database_internet_gateway_route"></a> [create\_database\_internet\_gateway\_route](#input\_create\_database\_internet\_gateway\_route) | Controls if an internet gateway route for public database access should be created | `bool` | `false` | no |
| <a name="input_create_database_nat_gateway_route"></a> [create\_database\_nat\_gateway\_route](#input\_create\_database\_nat\_gateway\_route) | Controls if a nat gateway route should be created to give internet access to the database subnets | `bool` | `false` | no | | <a name="input_create_database_nat_gateway_route"></a> [create\_database\_nat\_gateway\_route](#input\_create\_database\_nat\_gateway\_route) | Controls if a nat gateway route should be created to give internet access to the database subnets | `bool` | `false` | no |
| <a name="input_create_database_subnet_group"></a> [create\_database\_subnet\_group](#input\_create\_database\_subnet\_group) | Controls if database subnet group should be created (n.b. database\_subnets must also be set) | `bool` | `true` | no | | <a name="input_create_database_subnet_group"></a> [create\_database\_subnet\_group](#input\_create\_database\_subnet\_group) | Controls if database subnet group should be created (n.b. database\_subnets must also be set) | `bool` | `true` | no |
...@@ -455,6 +455,10 @@ No modules. ...@@ -455,6 +455,10 @@ No modules.
| <a name="input_intra_subnet_tags"></a> [intra\_subnet\_tags](#input\_intra\_subnet\_tags) | Additional tags for the intra subnets | `map(string)` | `{}` | no | | <a name="input_intra_subnet_tags"></a> [intra\_subnet\_tags](#input\_intra\_subnet\_tags) | Additional tags for the intra subnets | `map(string)` | `{}` | no |
| <a name="input_intra_subnets"></a> [intra\_subnets](#input\_intra\_subnets) | A list of intra subnets | `list(string)` | `[]` | no | | <a name="input_intra_subnets"></a> [intra\_subnets](#input\_intra\_subnets) | A list of intra subnets | `list(string)` | `[]` | no |
| <a name="input_ipv4_ipam_pool_id"></a> [ipv4\_ipam\_pool\_id](#input\_ipv4\_ipam\_pool\_id) | (Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR. | `string` | `null` | no | | <a name="input_ipv4_ipam_pool_id"></a> [ipv4\_ipam\_pool\_id](#input\_ipv4\_ipam\_pool\_id) | (Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR. | `string` | `null` | no |
| <a name="input_ipv4_netmask_length"></a> [ipv4\_netmask\_length](#input\_ipv4\_netmask\_length) | (Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4\_ipam\_pool\_id. | `number` | `null` | no |
| <a name="input_ipv6_cidr"></a> [ipv6\_cidr](#input\_ipv6\_cidr) | (Optional) IPv6 CIDR block to request from an IPAM Pool. Can be set explicitly or derived from IPAM using `ipv6_netmask_length`. | `string` | `null` | no |
| <a name="input_ipv6_ipam_pool_id"></a> [ipv6\_ipam\_pool\_id](#input\_ipv6\_ipam\_pool\_id) | (Optional) IPAM Pool ID for a IPv6 pool. Conflicts with `assign_generated_ipv6_cidr_block`. | `string` | `null` | no |
| <a name="input_ipv6_netmask_length"></a> [ipv6\_netmask\_length](#input\_ipv6\_netmask\_length) | (Optional) Netmask length to request from IPAM Pool. Conflicts with `ipv6_cidr_block`. This can be omitted if IPAM pool as a `allocation_default_netmask_length` set. Valid values: `56`. | `number` | `null` | no |
| <a name="input_manage_default_network_acl"></a> [manage\_default\_network\_acl](#input\_manage\_default\_network\_acl) | Should be true to adopt and manage Default Network ACL | `bool` | `false` | no | | <a name="input_manage_default_network_acl"></a> [manage\_default\_network\_acl](#input\_manage\_default\_network\_acl) | Should be true to adopt and manage Default Network ACL | `bool` | `false` | no |
| <a name="input_manage_default_route_table"></a> [manage\_default\_route\_table](#input\_manage\_default\_route\_table) | Should be true to manage default route table | `bool` | `false` | no | | <a name="input_manage_default_route_table"></a> [manage\_default\_route\_table](#input\_manage\_default\_route\_table) | Should be true to manage default route table | `bool` | `false` | no |
| <a name="input_manage_default_security_group"></a> [manage\_default\_security\_group](#input\_manage\_default\_security\_group) | Should be true to adopt and manage default security group | `bool` | `false` | no | | <a name="input_manage_default_security_group"></a> [manage\_default\_security\_group](#input\_manage\_default\_security\_group) | Should be true to adopt and manage default security group | `bool` | `false` | no |
...@@ -516,6 +520,7 @@ No modules. ...@@ -516,6 +520,7 @@ No modules.
| <a name="input_secondary_cidr_blocks"></a> [secondary\_cidr\_blocks](#input\_secondary\_cidr\_blocks) | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool | `list(string)` | `[]` | no | | <a name="input_secondary_cidr_blocks"></a> [secondary\_cidr\_blocks](#input\_secondary\_cidr\_blocks) | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool | `list(string)` | `[]` | no |
| <a name="input_single_nat_gateway"></a> [single\_nat\_gateway](#input\_single\_nat\_gateway) | Should be true if you want to provision a single shared NAT Gateway across all of your private networks | `bool` | `false` | no | | <a name="input_single_nat_gateway"></a> [single\_nat\_gateway](#input\_single\_nat\_gateway) | Should be true if you want to provision a single shared NAT Gateway across all of your private networks | `bool` | `false` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| <a name="input_use_ipam_pool"></a> [use\_ipam\_pool](#input\_use\_ipam\_pool) | Determines whether IPAM pool is used for CIDR allocation | `bool` | `false` | no |
| <a name="input_vpc_flow_log_permissions_boundary"></a> [vpc\_flow\_log\_permissions\_boundary](#input\_vpc\_flow\_log\_permissions\_boundary) | The ARN of the Permissions Boundary for the VPC Flow Log IAM Role | `string` | `null` | no | | <a name="input_vpc_flow_log_permissions_boundary"></a> [vpc\_flow\_log\_permissions\_boundary](#input\_vpc\_flow\_log\_permissions\_boundary) | The ARN of the Permissions Boundary for the VPC Flow Log IAM Role | `string` | `null` | no |
| <a name="input_vpc_flow_log_tags"></a> [vpc\_flow\_log\_tags](#input\_vpc\_flow\_log\_tags) | Additional tags for the VPC Flow Logs | `map(string)` | `{}` | no | | <a name="input_vpc_flow_log_tags"></a> [vpc\_flow\_log\_tags](#input\_vpc\_flow\_log\_tags) | Additional tags for the VPC Flow Logs | `map(string)` | `{}` | no |
| <a name="input_vpc_tags"></a> [vpc\_tags](#input\_vpc\_tags) | Additional tags for the VPC | `map(string)` | `{}` | no | | <a name="input_vpc_tags"></a> [vpc\_tags](#input\_vpc\_tags) | Additional tags for the VPC | `map(string)` | `{}` | no |
......
...@@ -42,13 +42,15 @@ Note that this example may create resources which can cost money (AWS Elastic IP ...@@ -42,13 +42,15 @@ Note that this example may create resources which can cost money (AWS Elastic IP
| Name | Source | Version | | Name | Source | Version |
|------|--------|---------| |------|--------|---------|
| <a name="module_vpc"></a> [vpc](#module\_vpc) | ../.. | n/a | | <a name="module_vpc_ipam_set_cidr"></a> [vpc\_ipam\_set\_cidr](#module\_vpc\_ipam\_set\_cidr) | ../.. | n/a |
| <a name="module_vpc_ipam_set_netmask"></a> [vpc\_ipam\_set\_netmask](#module\_vpc\_ipam\_set\_netmask) | ../.. | n/a |
## Resources ## Resources
| Name | Type | | Name | Type |
|------|------| |------|------|
| [aws_vpc_ipam.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam) | resource | | [aws_vpc_ipam.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam) | resource |
| [aws_vpc_ipam_pool.ipv6](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool) | resource |
| [aws_vpc_ipam_pool.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool) | resource | | [aws_vpc_ipam_pool.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool) | resource |
| [aws_vpc_ipam_pool_cidr.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr) | resource | | [aws_vpc_ipam_pool_cidr.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr) | resource |
| [aws_vpc_ipam_preview_next_cidr.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_preview_next_cidr) | resource | | [aws_vpc_ipam_preview_next_cidr.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_preview_next_cidr) | resource |
......
...@@ -6,7 +6,8 @@ locals { ...@@ -6,7 +6,8 @@ locals {
name = "ex-${replace(basename(path.cwd), "_", "-")}" name = "ex-${replace(basename(path.cwd), "_", "-")}"
region = "eu-west-1" region = "eu-west-1"
partition = cidrsubnets(aws_vpc_ipam_preview_next_cidr.this.cidr, 2, 2) azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
preview_partition = cidrsubnets(aws_vpc_ipam_preview_next_cidr.this.cidr, 2, 2, 2)
tags = { tags = {
Example = local.name Example = local.name
...@@ -19,21 +20,58 @@ locals { ...@@ -19,21 +20,58 @@ locals {
# VPC Module # VPC Module
################################################################################ ################################################################################
module "vpc" { # IPv4
module "vpc_ipam_set_netmask" {
source = "../.." source = "../.."
name = local.name name = "${local.name}-set-netmask"
private_subnets = cidrsubnets(local.partition[0], 2, 2) use_ipam_pool = true
public_subnets = cidrsubnets(local.partition[1], 2, 2) ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id
ipv4_netmask_length = 16
azs = local.azs
private_subnets = cidrsubnets(local.preview_partition[0], 2, 2, 2)
public_subnets = cidrsubnets(local.preview_partition[1], 2, 2, 2)
tags = local.tags
depends_on = [
aws_vpc_ipam_pool_cidr.this
]
}
module "vpc_ipam_set_cidr" {
source = "../.."
name = "${local.name}-set-cidr"
use_ipam_pool = true
ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id
azs = ["${local.region}a", "${local.region}b"] cidr = "10.1.0.0/16"
cidr = aws_vpc_ipam_preview_next_cidr.this.cidr azs = local.azs
private_subnets = ["10.1.1.0/24", "10.1.2.0/24", "10.1.3.0/24"]
public_subnets = ["10.1.11.0/24", "10.1.12.0/24", "10.1.13.0/24"]
tags = local.tags tags = local.tags
} }
# # IPv6 - Requires having a CIDR plus its message and signature (see below)
# module "vpc_ipv6_ipam_set_netmask" {
# source = "../.."
# name = "${local.name}-ipv6-set-netmask"
# use_ipam_pool = true
# ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id
# ipv6_ipam_pool_id = aws_vpc_ipam_pool.ipv6.id
# ipv6_netmask_length = 56
# azs = local.azs
# tags = local.tags
# }
################################################################################ ################################################################################
# Supporting Resources # Supporting Resources
################################################################################ ################################################################################
...@@ -56,25 +94,54 @@ resource "aws_vpc_ipam" "this" { ...@@ -56,25 +94,54 @@ resource "aws_vpc_ipam" "this" {
operating_regions { operating_regions {
region_name = local.region region_name = local.region
} }
tags = local.tags
} }
# IPv4
resource "aws_vpc_ipam_pool" "this" { resource "aws_vpc_ipam_pool" "this" {
description = "IPv4 pool"
address_family = "ipv4" address_family = "ipv4"
ipam_scope_id = aws_vpc_ipam.this.private_default_scope_id ipam_scope_id = aws_vpc_ipam.this.private_default_scope_id
locale = local.region locale = local.region
allocation_default_netmask_length = 24 allocation_default_netmask_length = 16
tags = local.tags
} }
resource "aws_vpc_ipam_pool_cidr" "this" { resource "aws_vpc_ipam_pool_cidr" "this" {
ipam_pool_id = aws_vpc_ipam_pool.this.id ipam_pool_id = aws_vpc_ipam_pool.this.id
cidr = "10.0.0.0/16" cidr = "10.0.0.0/8"
} }
resource "aws_vpc_ipam_preview_next_cidr" "this" { resource "aws_vpc_ipam_preview_next_cidr" "this" {
ipam_pool_id = aws_vpc_ipam_pool.this.id ipam_pool_id = aws_vpc_ipam_pool.this.id
netmask_length = 20
depends_on = [ depends_on = [
aws_vpc_ipam_pool_cidr.this aws_vpc_ipam_pool_cidr.this
] ]
} }
# IPv6
resource "aws_vpc_ipam_pool" "ipv6" {
description = "IPv6 pool"
address_family = "ipv6"
ipam_scope_id = aws_vpc_ipam.this.public_default_scope_id
locale = local.region
allocation_default_netmask_length = 56
publicly_advertisable = false
aws_service = "ec2"
tags = local.tags
}
# # Requires having a CIDR plus its message and signature
# resource "aws_vpc_ipam_pool_cidr" "ipv6" {
# ipam_pool_id = aws_vpc_ipam_pool.ipv6.id
# cidr = var.ipv6_cidr
# cidr_authorization_context {
# message = var.message
# signature = var.signature
# }
# }
This diff is collapsed.
...@@ -20,15 +20,20 @@ locals { ...@@ -20,15 +20,20 @@ locals {
resource "aws_vpc" "this" { resource "aws_vpc" "this" {
count = local.create_vpc ? 1 : 0 count = local.create_vpc ? 1 : 0
cidr_block = var.cidr cidr_block = var.use_ipam_pool ? null : var.cidr
ipv4_ipam_pool_id = var.ipv4_ipam_pool_id ipv4_ipam_pool_id = var.ipv4_ipam_pool_id
ipv4_netmask_length = var.ipv4_netmask_length
assign_generated_ipv6_cidr_block = var.enable_ipv6 && !var.use_ipam_pool ? true : null
ipv6_cidr_block = var.ipv6_cidr
ipv6_ipam_pool_id = var.ipv6_ipam_pool_id
ipv6_netmask_length = var.ipv6_netmask_length
instance_tenancy = var.instance_tenancy instance_tenancy = var.instance_tenancy
enable_dns_hostnames = var.enable_dns_hostnames enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = var.enable_dns_support enable_dns_support = var.enable_dns_support
enable_classiclink = null # https://github.com/hashicorp/terraform/issues/31730 enable_classiclink = null # https://github.com/hashicorp/terraform/issues/31730
enable_classiclink_dns_support = null # https://github.com/hashicorp/terraform/issues/31730 enable_classiclink_dns_support = null # https://github.com/hashicorp/terraform/issues/31730
assign_generated_ipv6_cidr_block = var.enable_ipv6
tags = merge( tags = merge(
{ "Name" = var.name }, { "Name" = var.name },
......
...@@ -11,7 +11,7 @@ variable "name" { ...@@ -11,7 +11,7 @@ variable "name" {
} }
variable "cidr" { variable "cidr" {
description = "(Optional) The IPv4 CIDR block for the VPC." description = "(Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`"
type = string type = string
default = "0.0.0.0/0" default = "0.0.0.0/0"
} }
...@@ -1190,12 +1190,42 @@ variable "flow_log_per_hour_partition" { ...@@ -1190,12 +1190,42 @@ variable "flow_log_per_hour_partition" {
default = false default = false
} }
variable "use_ipam_pool" {
description = "Determines whether IPAM pool is used for CIDR allocation"
type = bool
default = false
}
variable "ipv4_ipam_pool_id" { variable "ipv4_ipam_pool_id" {
description = "(Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR." description = "(Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR."
type = string type = string
default = null default = null
} }
variable "ipv4_netmask_length" {
description = "(Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4_ipam_pool_id."
type = number
default = null
}
variable "ipv6_cidr" {
description = "(Optional) IPv6 CIDR block to request from an IPAM Pool. Can be set explicitly or derived from IPAM using `ipv6_netmask_length`."
type = string
default = null
}
variable "ipv6_ipam_pool_id" {
description = "(Optional) IPAM Pool ID for a IPv6 pool. Conflicts with `assign_generated_ipv6_cidr_block`."
type = string
default = null
}
variable "ipv6_netmask_length" {
description = "(Optional) Netmask length to request from IPAM Pool. Conflicts with `ipv6_cidr_block`. This can be omitted if IPAM pool as a `allocation_default_netmask_length` set. Valid values: `56`."
type = number
default = null
}
variable "putin_khuylo" { variable "putin_khuylo" {
description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!" description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!"
type = bool type = bool
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment