This example demonstrates a matching spoke VPC that is consistent, cost efficient and automatable to join to the example hub account to consume centralised network services.
- Consistent: allows reasoning about all of your AWS organization's network state
- Cost efficient: Removes requirement for per-VPC NAT Gateway and VPC Endpoints
- Automatable: Simple VPC deployment can be tied in to other processes such as account creation automation.
The following resources will be deployed by this example:
- a VPC with a CIDR assigned by AWS VPC IP Address Manager
- 3 Endpoint Subnets
- 3 Private Subnets
- Local VPC Endpoints
- TGW Attachment, Association and Propagation
- Route 53 Resolver Rule Association
- Private Hosted Zone
The resources deployed and the architectural pattern they follow are provided for demonstration and testing purposes but are based on and inspired by AWS best practice and articles.
- https://aws.amazon.com/blogs/architecture/field-notes-how-to-scale-your-networks-on-amazon-web-services/
- https://aws.amazon.com/blogs/industries/defining-an-aws-multi-account-strategy-for-a-digital-bank/
- https://aws.amazon.com/blogs/security/protect-your-remote-workforce-by-using-a-managed-dns-firewall-and-network-firewall/
- https://aws.amazon.com/blogs/architecture/field-notes-working-with-route-tables-in-aws-transit-gateway/
- https://docs.aws.amazon.com/vpc/latest/tgw/transit-gateway-isolated-shared.html
- https://aws.amazon.com/blogs/security/simplify-dns-management-in-a-multiaccount-environment-with-route-53-resolver/
- Terraform ~> 1.1
- AWS provider ~> 3.0
- AWS CLI
- Git CLI
- AWS Organization
- RAM enabled to Org
- IPAM delegated to network hub account
- Centralised network account with Hub Solution deployed
- Spoke account to deploy into
- IAM role with required permissions
- Tag all roles with automation = true
Customisation If you do not define a remote backend Terraform will use the local directory to store the local backend files including tfstate. Examples of how to customise the Terraform backend are included but commented out.
Example GitLab HTTP backend for use with GitLab CI.
Update network hub account ID in config.auto.tfvars per environment.
aws_region = "eu-west-2"
vpc_endpoints = ["s3"]
centralised_vpc_endpoints = ["ec2", "rds", "sqs", "sns", "ssm", "logs", "ssmmessages", "ec2messages", "autoscaling", "ecs", "athena"]
env_config = {
dev = {
network_hub_account_number = "<Network_Hub_Account_ID>"
tgw_route_tables = ["shared", "dev"]
root_domain = "network-dev.internal."
}
test = {
network_hub_account_number = "<Network_Hub_Account_ID>"
tgw_route_tables = ["shared", "dev"]
root_domain = "network-test.internal."
}
preprod = {
network_hub_account_number = "<Network_Hub_Account_ID>"
tgw_route_tables = ["shared", "dev"]
root_domain = "network-preprod.internal."
}
prod = {
network_hub_account_number = "<Network_Hub_Account_ID>"
tgw_route_tables = ["shared", "prod"]
root_domain = "network-prod.internal."
}
}
When deploying from your local machine having configured the TF Backend in the code you need to ensure you have access to read and write to the backend - possible backends include HTTP, Consul, Postgres, Artifactory, S3 or S3 + DynamoDB. We initialise the Terraform, complete the validate and format. Review the plan and then apply.
terraform init
terraform validate
- set environment for deployment
export TF_VAR_environment=" **ENV** "
Set-Item -Path env:TF_VAR_environment -Value “ **ENV** “
(Possible Env values * dev, test, preprod, prod)
terraform plan
terraform apply
orterraform apply --auto-approve
Tags are added to all AWS resources through use of the tag configuration of the AWS Provider.
As not all AWS resources support default tags passed from the provider (EC2 Auto-Scaling Group + Launch Template) We pass the tags as a variable (Map(string) - these are defined in the root locals.tf file.
Example Tags - locals.tf
tags = {
Product = "Network_Automation"
Owner = "GitHub"
Project_ID = "12345"
}
Remember to clean up after your work is complete. You can do that by doing terraform destroy
.
Note that this command will delete all the resources previously created by Terraform.
Name | Version |
---|---|
terraform | ~> 1.1 |
aws | ~> 3.0 |
Name | Version |
---|---|
aws | ~> 3.0 |
aws.network_hub | ~> 3.0 |
Name | Source | Version |
---|---|---|
dns | ./modules/dns | n/a |
network | ./modules/network | n/a |
Name | Type |
---|---|
aws_availability_zones.available | data source |
aws_ec2_transit_gateway.org_env | data source |
aws_ec2_transit_gateway_route_table.associate | data source |
aws_ec2_transit_gateway_route_table.org_env | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
aws_region | AWS region being deployed to | string |
n/a | yes |
az_count | Number of availability zones | number |
2 |
no |
centralised_vpc_endpoints | Which centralised VPC endpoints to consume | list(string) |
n/a | yes |
env_config | Map of objects for per environment configuration | map(object({ |
n/a | yes |
environment | Deployment environment passed as argument or environment variable | string |
n/a | yes |
tags | Default tags to apply to all resources | map(string) |
n/a | yes |
vpc_endpoints | Which local VPC endpoints to deploy | list(string) |
n/a | yes |
vpc_name | Name of the VPC | string |
"spoke" |
no |
Name | Description |
---|---|
vpc_id | VPC ID used for other modules |
Name | Version |
---|---|
terraform | ~> 1.1 |
aws | ~> 3.0 |
Name | Version |
---|---|
aws | ~> 3.0 |
aws.network_hub | ~> 3.0 |
No modules.
Name | Description | Type | Default | Required |
---|---|---|---|---|
aws_region | AWS region being deployed to | string |
n/a | yes |
az_names | A list of the Availability Zone names available to the account | list(string) |
n/a | yes |
environment | Deployment environment passed as argument or environment variable | string |
n/a | yes |
interface_endpoints | Object representing the region and services to create interface endpoints for | map(string) |
n/a | yes |
network_hub_account_number | Network Hub account ID | string |
n/a | yes |
tgw | TGW ID for VPC attachments | string |
n/a | yes |
tgw_association | TGW route table to associate to | string |
n/a | yes |
tgw_route_table | TGW route tables for VPC association and propagation | map(string) |
n/a | yes |
vpc_name | Name of the VPC | string |
"spoke" |
no |
Name | Description |
---|---|
vpc_id | VPC ID used for other modules |
Name | Version |
---|---|
terraform | ~> 1.1 |
aws | ~> 3.0 |
Name | Version |
---|---|
aws | ~> 3.0 |
aws.network_hub | ~> 3.0 |
No modules.
Name | Type |
---|---|
aws_route53_record.ns_record | resource |
aws_route53_resolver_rule_association.root_domain | resource |
aws_route53_vpc_association_authorization.delegated_private | resource |
aws_route53_vpc_association_authorization.endpoint_phz | resource |
aws_route53_zone.delegated_private | resource |
aws_route53_zone_association.delegated_private | resource |
aws_route53_zone_association.endpoint_phz | resource |
aws_caller_identity.current | data source |
aws_route53_resolver_rule.root_domain | data source |
aws_route53_zone.centralised_endpoints | data source |
aws_route53_zone.selected | data source |
aws_vpc.endpoint | data source |
aws_vpc.selected | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
aws_region | AWS region being deployed to | string |
n/a | yes |
centralised_vpc_endpoints | Which centralised VPC endpoints to consume | map(string) |
n/a | yes |
environment | Deployment environment passed as argument or environment variable | string |
n/a | yes |
network_hub_account_number | Network Hub account ID | string |
n/a | yes |
root_domain | Root domain for the delegated private hosted zone | string |
n/a | yes |
vpc_id | VPC ID to associate delegated subdomain to | string |
n/a | yes |
No outputs.