infra/region-host: optional zone-scoped Route53 DNS-01 policy
route53_zone_ids (default empty = no statement, flagship untouched); tito's stack names the tito.io zone so the box role can write _acme-challenge TXTs for *.go.tito.io — no DNS token on disk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 files changed,
+35
−0
infra/modules/region-host/main.tf+29 −0infra/modules/region-host/variables.tf+6 −0
diff --git a/infra/modules/region-host/main.tf b/infra/modules/region-host/main.tf| index cee383b1b..8d378e90a 100644 |
| --- a/infra/modules/region-host/main.tf |
| +++ b/infra/modules/region-host/main.tf |
| @@ -99,6 +99,35 @@ resource "aws_iam_role_policy" "host_buckets" { |
| }) |
| } |
| +# Wildcard-cert DNS-01 (edge wildcard.go, CARLOS_DNS_PROVIDER=route53): |
| +# write challenge TXTs into the named zones only. ListHostedZonesByName has |
| +# no resource-level scoping in IAM, hence the split statement. |
| +resource "aws_iam_role_policy" "host_route53" { |
| + count = length(var.route53_zone_ids) > 0 ? 1 : 0 |
| + name = "${var.iam_name}-route53" |
| + role = aws_iam_role.host.id |
| + policy = jsonencode({ |
| + Version = "2012-10-17" |
| + Statement = [ |
| + { |
| + Effect = "Allow" |
| + Action = ["route53:ChangeResourceRecordSets"] |
| + Resource = [for z in var.route53_zone_ids : "arn:aws:route53:::hostedzone/${z}"] |
| + }, |
| + { |
| + Effect = "Allow" |
| + Action = ["route53:GetChange"] |
| + Resource = "arn:aws:route53:::change/*" |
| + }, |
| + { |
| + Effect = "Allow" |
| + Action = ["route53:ListHostedZonesByName"] |
| + Resource = "*" |
| + } |
| + ] |
| + }) |
| +} |
| + |
| resource "aws_iam_role_policy_attachment" "host_ssm" { |
| role = aws_iam_role.host.name |
| policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" |
diff --git a/infra/modules/region-host/variables.tf b/infra/modules/region-host/variables.tf| index 2156aff47..e73e783be 100644 |
| --- a/infra/modules/region-host/variables.tf |
| +++ b/infra/modules/region-host/variables.tf |
| @@ -66,3 +66,9 @@ variable "ami_owner" { |
| type = string |
| default = "136693071363" # Debian |
| } |
| + |
| +variable "route53_zone_ids" { |
| + description = "Hosted-zone IDs the host may write ACME DNS-01 challenge records into (wildcard certs, CARLOS_DNS_PROVIDER=route53). Empty = no Route53 access." |
| + type = list(string) |
| + default = [] |
| +} |