Última revisão: maio de 2026
Construa os serviços da AWS do exame ANS-C01 com Terraform puro — um bloco de cada vez, cada um vinculado a um domínio do exame. O mesmo código funciona no OpenTofu.
Ao final deste laboratório, você terá provisionado, com Terraform simples, a arquitetura de backbone multi-VPC canônica da AWS — duas VPCs dual-stack (IPv4 + IPv6) na mesma região, conectadas através de um Transit Gateway com associações explícitas de tabelas de rotas e VPC Flow Logs apoiados por CloudWatch na VPC primária para que você possa realmente ver o que está atravessando sua rede. Esta é a arquitetura que toda questão multi-VPC do ANS-C01 assume.
Cada recurso é Terraform puro. Coloque os trechos em um único main.tf, execute terraform init, então terraform apply passo a passo.
>= 1.5 ou OpenTofu >= 1.6.us-east-1.A maior parte deste laboratório é barata ou gratuita, mas Transit Gateway não é:
A taxa horária do TGW é o custo deste laboratório. Dois anexos × $0.05/hora × 24 horas × 30 dias ≈ $72/mês enquanto estiver em execução. Destrua assim que terminar de explorar — TGW é a maior armadilha de custos em qualquer laboratório ANS-C01.
Abertura padrão. O Transit Gateway é regional — todos os anexos devem estar na região onde o TGW reside. Para conectividade entre regiões, você adicionaria o peering de TGW (fora do escopo para v1). Usamos us-east-1 como padrão.
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Project = "certlabpro-ans-c01"
ManagedBy = "terraform"
}
}
}
data "aws_availability_zones" "available" {
state = "available"
}O ANS-C01 testa especificamente VPCs dual-stack — a AWS agora atribui por padrão um IPv6 /56 a cada nova VPC se você definir assign_generated_ipv6_cidr_block = true. O domínio Network Design do exame testa tanto a matemática de planejamento de CIDR IPv4 (/16s não sobrepostos se você quiser fazer peering ou anexar via TGW) quanto a derivação de sub-redes IPv6 (cada sub-rede obtém um /64 esculpido do /56 da VPC).
Nós atribuímos 10.0.0.0/16 para IPv4 e um IPv6 /56 gerado automaticamente pela AWS. A única sub-rede aqui usa um bloco IPv4 /24 e um bloco IPv6 /64 esculpido do /56 da VPC — cidrsubnet é o recurso integrado do Terraform para essa matemática. O internet gateway é dual-stack por padrão nas regiões modernas da AWS.
resource "aws_vpc" "primary" {
cidr_block = "10.0.0.0/16"
assign_generated_ipv6_cidr_block = true
enable_dns_hostnames = true
tags = { Name = "certlabpro-ans-c01-primary" }
}
resource "aws_subnet" "primary_a" {
vpc_id = aws_vpc.primary.id
cidr_block = "10.0.1.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.primary.ipv6_cidr_block, 8, 1)
availability_zone = data.aws_availability_zones.available.names[0]
assign_ipv6_address_on_creation = true
tags = { Name = "certlabpro-ans-c01-primary-a" }
}
resource "aws_internet_gateway" "primary" {
vpc_id = aws_vpc.primary.id
}Construímos uma segunda VPC em 10.1.0.0/16 — propositadamente não sobreposta ao 10.0.0.0/16 da VPC #1. O ANS-C01 insiste nesta regra de design porque no momento em que você deseja conectar duas VPCs (peering, TGW, qualquer coisa), CIDRs sobrepostos impedem isso na camada da API da AWS. Você não pode rotear para um CIDR que também é reivindicado localmente.
A VPC #2 também recebe seu próprio IPv6 /56 gerado automaticamente pela AWS (cada VPC recebe um bloco globalmente único, então não há risco de sobreposição de IPv6 por padrão). A matemática de 'escultura' da sub-rede tem o mesmo formato do Passo 2.
resource "aws_vpc" "secondary" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
enable_dns_hostnames = true
tags = { Name = "certlabpro-ans-c01-secondary" }
}
resource "aws_subnet" "secondary_a" {
vpc_id = aws_vpc.secondary.id
cidr_block = "10.1.1.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.secondary.ipv6_cidr_block, 8, 1)
availability_zone = data.aws_availability_zones.available.names[0]
assign_ipv6_address_on_creation = true
tags = { Name = "certlabpro-ans-c01-secondary-a" }
}O Transit Gateway é o hub. Ele escala para milhares de anexos de VPC, suporta compartilhamento entre contas via AWS Resource Access Manager (RAM) e oferece uma única tabela de rotas para raciocinar, em vez de N² conexões de peering. O ANS-C01 testa esta escolha de hub-and-spoke em detrimento do peering de VPC sempre que a questão menciona "mais de três VPCs" ou "à medida que nossa rede cresce".
Criamos o TGW com associação e propagação de tabela de rotas padrão desabilitadas — esse é o padrão mais testado do ANS-C01 porque o força a ser explícito sobre quais anexos preenchem quais tabelas de rotas. A associação automática é a configuração de conveniência; a manual é a configuração amigável à auditoria.
O recurso de anexo é a ponte por VPC. Com ambas as VPCs anexadas, o TGW conhece os CIDRs de ambas; ainda precisamos adicionar rotas da tabela de rotas principal de cada VPC apontando para o TGW (Passo 5).
resource "aws_ec2_transit_gateway" "hub" {
description = "certlabpro-ans-c01 hub"
default_route_table_association = "disable"
default_route_table_propagation = "disable"
multicast_support = "disable"
tags = { Name = "certlabpro-ans-c01-tgw" }
}
resource "aws_ec2_transit_gateway_route_table" "main" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
tags = { Name = "certlabpro-ans-c01-tgw-rt" }
}
resource "aws_ec2_transit_gateway_vpc_attachment" "primary" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
vpc_id = aws_vpc.primary.id
subnet_ids = [aws_subnet.primary_a.id]
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
}
resource "aws_ec2_transit_gateway_vpc_attachment" "secondary" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
vpc_id = aws_vpc.secondary.id
subnet_ids = [aws_subnet.secondary_a.id]
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
}
resource "aws_ec2_transit_gateway_route_table_association" "primary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.primary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_association" "secondary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.secondary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_propagation" "primary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.primary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_propagation" "secondary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.secondary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}O TGW do Passo 4 conhece ambas as VPCs, mas a tabela de rotas de cada VPC ainda não sabe como alcançar a outra. Adicionamos rotas explícitas em ambas as direções: a tabela de rotas da VPC #1 envia tráfego 10.1.0.0/16 para o TGW, e vice-versa. O exame testa repetidamente este requisito de dois lados — "Eu anexei ambos ao TGW, por que eles não conseguem fazer ping?" é quase sempre uma rota de retorno ausente.
Finalmente, VPC Flow Logs. O domínio Network Monitoring do ANS-C01 os testa como a única maneira de ver quais pacotes estão realmente atravessando sua rede — aceitos, rejeitados e apenas metadados (5-tupla + bytes + pacotes + resultado). Nós os ativamos para a VPC primária, com logs fluindo para um grupo de logs dedicado do CloudWatch. A função IAM que anexamos é a que os Flow Logs assumem para gravar no grupo de logs.
Com as rotas no lugar e os Flow Logs em execução, o backbone está completo. Duas VPCs dual-stack, conectadas através de um TGW com roteamento explícito (amigável à auditoria), com visibilidade em nível de pacote no lado primário. Cada padrão adicional do ANS-C01 (Direct Connect Gateway, peering de TGW, NAT, PrivateLink, endpoints de VPC) se anexa a esta base.
resource "aws_route" "primary_to_secondary" {
route_table_id = aws_vpc.primary.main_route_table_id
destination_cidr_block = "10.1.0.0/16"
transit_gateway_id = aws_ec2_transit_gateway.hub.id
depends_on = [aws_ec2_transit_gateway_vpc_attachment.primary]
}
resource "aws_route" "secondary_to_primary" {
route_table_id = aws_vpc.secondary.main_route_table_id
destination_cidr_block = "10.0.0.0/16"
transit_gateway_id = aws_ec2_transit_gateway.hub.id
depends_on = [aws_ec2_transit_gateway_vpc_attachment.secondary]
}
# ── VPC Flow Logs ─────────────────────────────────────────────
resource "aws_cloudwatch_log_group" "vpc_flow" {
name = "/aws/vpc-flow/certlabpro-ans-c01-primary"
retention_in_days = 30
}
resource "aws_iam_role" "vpc_flow" {
name = "certlabpro-ans-c01-vpc-flow"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "vpc-flow-logs.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "vpc_flow" {
name = "write-flow-logs"
role = aws_iam_role.vpc_flow.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
]
Resource = aws_cloudwatch_log_group.vpc_flow.arn
}]
})
}
resource "aws_flow_log" "primary" {
vpc_id = aws_vpc.primary.id
traffic_type = "ALL"
log_destination_type = "cloud-watch-logs"
log_destination = aws_cloudwatch_log_group.vpc_flow.arn
iam_role_arn = aws_iam_role.vpc_flow.arn
max_aggregation_interval = 60
}terraform destroy derruba tudo neste laboratório, mas tenha cuidado com a ordem — os anexos do Transit Gateway levam de 5 a 10 minutos para serem desanexados, e o próprio TGW não pode ser excluído até que ambos os anexos tenham sido totalmente removidos. terraform destroy lida corretamente com o grafo de dependências, mas a operação não é rápida. Não use Ctrl-C no meio do destroy, ou você acabará com anexos parcialmente desanexados que terá que limpar via console.
A principal razão para destruir prontamente é a taxa horária do TGW — dois anexos a $0.05/hora cada = $72/mês combinados. O custo do laboratório aumenta rapidamente se você esquecer que ele está em execução.
O ANS-C01 abrange superfícies de rede que este laboratório não pode incluir — Direct Connect (sem ambiente de teste sem uma porta física), AWS Site-to-Site VPN (precisa de um endpoint do lado do cliente), endpoints de entrada/saída do Route 53 Resolver para DNS híbrido, PrivateLink + serviços de endpoint de VPC, AWS Network Firewall, AWS Global Accelerator, verificações de integridade + failover do Route 53, Network Access Analyzer, Reachability Analyzer, peering de Transit Gateway (entre regiões), Cloud WAN, AWS App Mesh e cenários específicos de BGP (filtragem de rotas, prepend, manipulação de AS-PATH).
Nós nos limitamos à arquitetura de backbone multi-VPC porque é a arquitetura mais testada no exame — anexos do Direct Connect, túneis VPN, DNS híbrido e PrivateLink todos se ancoram neste tipo de hub TGW. Entenda o hub-and-spoke corretamente; os tipos de spoke são extensões dele.
Para as superfícies não provisionadas, as seções Navegar, Guia e Editorial desta página de certificação contêm cobertura conceitual. Um laboratório de acompanhamento adicionando Route 53 Resolver + um anexo VPN + PrivateLink completaria a história da rede híbrida.