diff --git a/12-vpc/vpc-main/README.md b/12-vpc/vpc-main/README.md new file mode 100755 index 0000000..d7a2add --- /dev/null +++ b/12-vpc/vpc-main/README.md @@ -0,0 +1,9 @@ +## Usage + +To run this example you need to execute: + +```sh +$ terraform init +$ terraform plan +$ terraform apply +``` \ No newline at end of file diff --git a/12-vpc/vpc-main/main.tf b/12-vpc/vpc-main/main.tf new file mode 100755 index 0000000..2cc3bae --- /dev/null +++ b/12-vpc/vpc-main/main.tf @@ -0,0 +1,15 @@ +provider "aws" { + region = var.region +} + +module "vpc-main" { + source = "../../modules/12-vpc/vpc-main" + + enable_dns_hostnames = true + enable_dns_support = true + enable_nat_gateway = true + single_nat_gateway = true + public_subnets = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"] + private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] + +} \ No newline at end of file diff --git a/12-vpc/vpc-main/outputs.tf b/12-vpc/vpc-main/outputs.tf new file mode 100755 index 0000000..6fa6f33 --- /dev/null +++ b/12-vpc/vpc-main/outputs.tf @@ -0,0 +1,84 @@ +output "vpc_id" { + description = "The ID of the VPC" + value = module.vpc-main.vpc_id +} + +output "vpc_cidr_block" { + description = "The CIDR block of the VPC" + value = module.vpc-main.vpc_cidr_block +} + +output "vpc_instance_tenancy" { + description = "Tenancy of instances spin up within VPC" + value = module.vpc-main.vpc_instance_tenancy +} + +output "vpc_enable_dns_support" { + description = "Whether or not the VPC has DNS support" + value = module.vpc-main.vpc_enable_dns_support +} + +output "vpc_enable_dns_hostnames" { + description = "Whether or not the VPC has DNS hostname support" + value = module.vpc-main.vpc_enable_dns_hostnames +} + +output "vpc_main_route_table_id" { + description = "The ID of the main route table associated with this VPC" + value = module.vpc-main.vpc_main_route_table_id +} + +output "private_subnets" { + description = "List of IDs of private subnets" + value = module.vpc-main.private_subnets +} + +output "private_subnet_arns" { + description = "List of ARNs of private subnets" + value = module.vpc-main.private_subnet_arns +} + +output "public_subnets" { + description = "List of IDs of public subnets" + value = module.vpc-main.public_subnets +} + +output "public_subnet_arns" { + description = "List of ARNs of public subnets" + value = module.vpc-main.public_subnet_arns +} + +output "public_route_table_ids" { + description = "List of IDs of public route tables" + value = module.vpc-main.public_route_table_ids +} + +output "private_route_table_ids" { + description = "List of IDs of private route tables" + value = module.vpc-main.private_route_table_ids +} + +output "nat_ids" { + description = "List of allocation ID of Elastic IPs created for AWS NAT Gateway" + value = module.vpc-main.nat_ids +} + +output "nat_public_ips" { + description = "List of public Elastic IPs created for AWS NAT Gateway" + value = module.vpc-main.nat_public_ips +} + +output "natgw_ids" { + description = "List of NAT Gateway IDs" + value = module.vpc-main.natgw_ids +} + +output "igw_id" { + description = "The ID of the Internet Gateway" + value = module.vpc-main.igw_id +} + +output "name" { + description = "The name of the VPC specified as argument to this module" + value = module.vpc-main.name +} \ No newline at end of file diff --git a/12-vpc/vpc-main/variables.tf b/12-vpc/vpc-main/variables.tf new file mode 100755 index 0000000..f551e0c --- /dev/null +++ b/12-vpc/vpc-main/variables.tf @@ -0,0 +1,9 @@ +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "region" { + type = string + default = "us-east-1" +} \ No newline at end of file diff --git a/12-vpc/vpc-main/versions.tf b/12-vpc/vpc-main/versions.tf new file mode 100755 index 0000000..ce68e92 --- /dev/null +++ b/12-vpc/vpc-main/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + } +} \ No newline at end of file diff --git a/modules/12-vpc/vpc-main/README.md b/modules/12-vpc/vpc-main/README.md new file mode 100755 index 0000000..0da5ebd --- /dev/null +++ b/modules/12-vpc/vpc-main/README.md @@ -0,0 +1,75 @@ +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.0 | +| aws | >= 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| aws | >= 4.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| aws_eip.nat | resource | +| aws_internet_gateway.igw | resource | +| aws_nat_gateway.nat_gateway | resource | +| aws_route.private_nat_gateway | resource | +| aws_route.public_internet_gateway | resource | +| aws_route_table.private | resource | +| aws_route_table.public | resource | +| aws_route_table_association.private | resource | +| aws_route_table_association.public | resource | +| aws_security_group.instance | resource | +| aws_security_group_rule.allow_server_http_inbound | resource | +| aws_security_group_rule.allow_server_outbound | resource | +| aws_subnet.private | resource | +| aws_subnet.public | resource | +| aws_vpc.vpc | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +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` | `"10.0.0.0/16"` | no | +| create\_igw | Controls if an Internet Gateway is created for public subnets and the related routes that connect them. | `bool` | `true` | no | +| create\_vpc | Controls if VPC should be created (it affects almost all resources) | `bool` | `true` | no | +| enable\_dns\_hostnames | Should be true to enable DNS hostnames in the VPC | `bool` | `false` | no | +| enable\_dns\_support | Should be true to enable DNS support in the VPC | `bool` | `true` | no | +| enable\_nat\_gateway | Should be true if you want to provision NAT Gateways for each of your private networks | `bool` | `false` | no | +| instance\_tenancy | A tenancy option for instances launched into the VPC | `string` | `"default"` | no | +| name | Name to be used on all the resources as identifier | `string` | `""` | no | +| nat\_gateway\_destination\_cidr\_block | Used to pass a custom destination route for private NAT Gateway. If not specified, the default 0.0.0.0/0 is used as a destination route. | `string` | `"0.0.0.0/0"` | no | +| private\_subnets | A list of private subnets inside the VPC | `list(string)` | `[]` | no | +| public\_subnets | A list of public subnets inside the VPC | `list(string)` | `[]` | no | +| 0 ? 1 : 0 + + vpc_id = aws_vpc.vpc[0].id + +} + +# --------------------------------------------------------------------------------------------------------------------- +# Public Routes +# --------------------------------------------------------------------------------------------------------------------- + +resource "aws_route_table" "public" { + count = var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0 + + vpc_id = aws_vpc.vpc[0].id + +} + +resource "aws_route" "public_internet_gateway" { + count = var.create_vpc && var.create_igw && length(var.public_subnets) > 0 ? 1 : 0 + + route_table_id = aws_route_table.public[0].id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw[0].id + + timeouts { + create = "5m" + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# Private Routes +# There Are As Many Routing Tables As The Number of NAT Gateways +# --------------------------------------------------------------------------------------------------------------------- + +resource "aws_route_table" "private" { + count = var.create_vpc && length(var.private_subnets) > 0 ? local.nat_gateway_count : 0 + + vpc_id = aws_vpc.vpc[0].id + +} + +# --------------------------------------------------------------------------------------------------------------------- +# Public Subnet +# --------------------------------------------------------------------------------------------------------------------- + +resource "aws_subnet" "public" { + count = var.create_vpc && length(var.public_subnets) > 0 ? length(var.public_subnets) : 0 + + vpc_id = aws_vpc.vpc[0].id + cidr_block = element(var.public_subnets, count.index) + +} + +# --------------------------------------------------------------------------------------------------------------------- +# Private Subnet +# --------------------------------------------------------------------------------------------------------------------- + +resource "aws_subnet" "private" { + count = var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0 + + vpc_id = aws_vpc.vpc[0].id + cidr_block = element(var.private_subnets, count.index) +} + +# --------------------------------------------------------------------------------------------------------------------- +# NAT Gateway +# --------------------------------------------------------------------------------------------------------------------- + +locals { + nat_gateway_count = var.single_nat_gateway ? 1 : length(var.private_subnets) + nat_gateway_ips = try(aws_eip.nat[*].id, []) +} + +resource "aws_eip" "nat" { + count = var.create_vpc && var.enable_nat_gateway ? local.nat_gateway_count : 0 + + vpc = true + +} + +resource "aws_nat_gateway" "nat_gateway" { + count = var.create_vpc && var.enable_nat_gateway ? local.nat_gateway_count : 0 + + allocation_id = element( + local.nat_gateway_ips, + count.index, + ) + subnet_id = element( + aws_subnet.public[*].id, + count.index, + ) + + depends_on = [aws_internet_gateway.igw] +} + +resource "aws_route" "private_nat_gateway" { + count = var.create_vpc && var.enable_nat_gateway ? local.nat_gateway_count : 0 + + route_table_id = element(aws_route_table.private[*].id, count.index) + destination_cidr_block = var.nat_gateway_destination_cidr_block + nat_gateway_id = element(aws_nat_gateway.nat_gateway[*].id, count.index) + + timeouts { + create = "10m" + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# Route Table Association +# --------------------------------------------------------------------------------------------------------------------- + +resource "aws_route_table_association" "private" { + count = var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0 + + subnet_id = element(aws_subnet.private[*].id, count.index) + route_table_id = element( + aws_route_table.private[*].id, + var.single_nat_gateway ? 0 : count.index, + ) +} + +resource "aws_route_table_association" "public" { + count = var.create_vpc && length(var.public_subnets) > 0 ? length(var.public_subnets) : 0 + + subnet_id = element(aws_subnet.public[*].id, count.index) + route_table_id = aws_route_table.public[0].id +} \ No newline at end of file diff --git a/modules/12-vpc/vpc-main/outputs.tf b/modules/12-vpc/vpc-main/outputs.tf new file mode 100755 index 0000000..503e5de --- /dev/null +++ b/modules/12-vpc/vpc-main/outputs.tf @@ -0,0 +1,84 @@ +output "vpc_id" { + description = "The ID of the VPC" + value = try(aws_vpc.vpc[0].id, "") +} + +output "vpc_cidr_block" { + description = "The CIDR block of the VPC" + value = try(aws_vpc.vpc[0].cidr_block, "") +} + +output "vpc_instance_tenancy" { + description = "Tenancy of instances spin up within VPC" + value = try(aws_vpc.vpc[0].instance_tenancy, "") +} + +output "vpc_enable_dns_support" { + description = "Whether or not the VPC has DNS support" + value = try(aws_vpc.vpc[0].enable_dns_support, "") +} + +output "vpc_enable_dns_hostnames" { + description = "Whether or not the VPC has DNS hostname support" + value = try(aws_vpc.vpc[0].enable_dns_hostnames, "") +} + +output "vpc_main_route_table_id" { + description = "The ID of the main route table associated with this VPC" + value = try(aws_vpc.vpc[0].main_route_table_id, "") +} + +output "private_subnets" { + description = "List of IDs of private subnets" + value = aws_subnet.private[*].id +} + +output "private_subnet_arns" { + description = "List of ARNs of private subnets" + value = aws_subnet.private[*].arn +} + +output "public_subnets" { + description = "List of IDs of public subnets" + value = aws_subnet.public[*].id +} + +output "public_subnet_arns" { + description = "List of ARNs of public subnets" + value = aws_subnet.public[*].arn +} + +output "public_route_table_ids" { + description = "List of IDs of public route tables" + value = aws_route_table.public[*].id +} + +output "private_route_table_ids" { + description = "List of IDs of private route tables" + value = aws_route_table.private[*].id +} + +output "nat_ids" { + description = "List of allocation ID of Elastic IPs created for AWS NAT Gateway" + value = aws_eip.nat[*].id +} + +output "nat_public_ips" { + description = "List of public Elastic IPs created for AWS NAT Gateway" + value = aws_eip.nat[*].public_ip +} + +output "natgw_ids" { + description = "List of NAT Gateway IDs" + value = aws_nat_gateway.nat_gateway[*].id +} + +output "igw_id" { + description = "The ID of the Internet Gateway" + value = try(aws_internet_gateway.igw[0].id, "") +} + +output "name" { + description = "The name of the VPC specified as argument to this module" + value = var.name +} \ No newline at end of file diff --git a/modules/12-vpc/vpc-main/variables.tf b/modules/12-vpc/vpc-main/variables.tf new file mode 100755 index 0000000..ad63dc4 --- /dev/null +++ b/modules/12-vpc/vpc-main/variables.tf @@ -0,0 +1,76 @@ +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "create_vpc" { + description = "Controls if VPC should be created (it affects almost all resources)" + type = bool + default = true +} + +variable "name" { + description = "Name to be used on all the resources as identifier" + type = string + default = "" +} + +variable "cidr" { + 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 + default = "10.0.0.0/16" +} + +variable "instance_tenancy" { + description = "A tenancy option for instances launched into the VPC" + type = string + default = "default" +} + +variable "public_subnets" { + description = "A list of public subnets inside the VPC" + type = list(string) + default = [] +} + +variable "private_subnets" { + description = "A list of private subnets inside the VPC" + type = list(string) + default = [] +} + +variable "enable_dns_hostnames" { + description = "Should be true to enable DNS hostnames in the VPC" + type = bool + default = false +} + +variable "enable_dns_support" { + description = "Should be true to enable DNS support in the VPC" + type = bool + default = true +} + +variable "enable_nat_gateway" { + description = "Should be true if you want to provision NAT Gateways for each of your private networks" + type = bool + default = false +} + +variable "nat_gateway_destination_cidr_block" { + description = "Used to pass a custom destination route for private NAT Gateway. If not specified, the default 0.0.0.0/0 is used as a destination route." + type = string + default = "0.0.0.0/0" +} + +variable "single_nat_gateway" { + description = "Should be true if you want to provision a single shared NAT Gateway across all of your private networks" + type = bool + default = false +} + +variable "create_igw" { + description = "Controls if an Internet Gateway is created for public subnets and the related routes that connect them." + type = bool + default = true +} \ No newline at end of file diff --git a/modules/12-vpc/vpc-main/versions.tf b/modules/12-vpc/vpc-main/versions.tf new file mode 100755 index 0000000..ce68e92 --- /dev/null +++ b/modules/12-vpc/vpc-main/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + } +} \ No newline at end of file