AWS - create VPC and a managed AD with terraform
Posted on October 18, 2021 (Last modified on October 23, 2024) • 2 min read • 416 wordsNote:
AWS offers a managed AD service, in two flavors (Samba-based, and “original” Microsoft). This shows how you create …
… with terraform.
Let’s go.
locals {
name = "testproject"
internal_dns_zone = "testproject.local"
ad_domain = "testad.aws"
cidr = "10.0.0.0/24"
azs = ["eu-central-1b", "eu-central-1c"]
database_subnets = [cidrsubnet(local.cidr, 3, 0), cidrsubnet(local.cidr, 3, 1)]
private_subnets = [cidrsubnet(local.cidr, 3, 2)]
public_subnets = [cidrsubnet(local.cidr, 3, 3)]
secret_winad_password = "uiuiuiui_super_secret"
tags = { broughttoyouby = "flypenguin ;)" }
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.7.0"
azs = local.azs
cidr = local.cidr
create_igw = true # for jump hosts, see also: https://is.gd/2Ry3H7
database_subnets = local.database_subnets
enable_dns_hostnames = true
enable_nat_gateway = true
enable_vpn_gateway = false # not yet
name = local.name
private_subnets = local.private_subnets
public_subnets = local.public_subnets
single_nat_gateway = true
}
resource "aws_directory_service_directory" "ad" {
name = local.ad_domain
password = local.secret_winad_password
edition = "Standard"
type = "MicrosoftAD"
tags = local.tags
vpc_settings {
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.database_subnets
}
}
resource "aws_route53_zone" "vpc" {
name = local.internal_dns_zone
vpc {
vpc_id = module.vpc.vpc_id
}
}
Now this was pretty easy. Problem: Windows thinks it is responsible for performing autoritative (I think) DNS lookups for the AD “domain”. And the internal DNS resolver has absolutely no clue about any AD related stuff. Amazon itself offers two possibilities:
This describes option (1), because in my eyes the VPC should not stop functioning without the AD (which it does if you give the AD primary DNS responsibility).
resource "aws_route53_resolver_endpoint" "ad_hcm_resolver" {
name = "ad-hcm-resolver"
direction = "OUTBOUND"
tags = local.tags
ip_address { subnet_id = module.vpc.database_subnets[0] }
ip_address { subnet_id = module.vpc.database_subnets[1] }
}
resource "aws_route53_resolver_rule" "ad_fwd" {
domain_name = local.ad_domain
name = "ad_hcm_forward"
rule_type = "FORWARD"
resolver_endpoint_id = aws_route53_resolver_endpoint.ad_hcm_resolver.id
tags = local.tags
target_ip { ip = sort(aws_directory_service_directory.ad.dns_ip_addresses)[0] }
target_ip { ip = sort(aws_directory_service_directory.ad.dns_ip_addresses)[1] }
}
# WE NEED THIS. without it does not work.
resource "aws_route53_resolver_rule_association" "ad_fwd" {
resolver_rule_id = aws_route53_resolver_rule.ad_fwd.id
vpc_id = module.vpc.vpc_id
}
WARNING: That stupid forwarder costs about 180$ / month (about 90¢ per IP address, and you must have two). It is REALLY expensive for what it does.