carlos / platform Public

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>
Paul Campbell bfbe48db101c3e7d6b674be44aea2ab1c8d8f7cc parent 5a5d611
2 files changed, +35 −0
  • infra/modules/region-host/main.tf +29 −0
  • infra/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 = []
+}