fix(agent-iam): add route53:GetChange for DNS propagation polling#289
fix(agent-iam): add route53:GetChange for DNS propagation polling#289jcastiarena wants to merge 1 commit intomainfrom
Conversation
The default agent IAM policy already grants ChangeResourceRecordSets and the Get/List HostedZone actions, but omits route53:GetChange on `arn:aws:route53:::change/*`. The AWS Terraform provider polls GetChange while waiting for a record to reach INSYNC after creation; without it, any scope that creates DNS records (static-files, k8s with external-dns, anything with a CNAME/A record) fails with AccessDenied *after* the record is successfully created. The failure mode is confusing because the record is visible in the console but the deploy rolls back. Found while installing the static-files scope at a customer POC. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Cross-cloud audit note — this fix lives correctly at the AWS layer ( Worth auditing analogous modules in this repo:
Not in scope for this PR. Flagging here so it doesn't fall through the cracks when an operator tries to install a DNS-creating scope on Azure or GCP and hits the same wall we hit on AWS. Related downstream PR documenting the AWS operator experience: nullplatform/scopes-static-files#8. |
|
Closing — permission is scope-specific, not vanilla agent. After discussion with the team (cc @agustincelentano), we concluded that The right place for this permission is in each customer's
The Architectural principle: the vanilla agent IAM ( |
Summary
The default IAM policy attached by
infrastructure/aws/iam/agentalready grantsChangeResourceRecordSets,ListResourceRecordSets, and theGet/List HostedZone*actions onarn:aws:route53:::hostedzone/*, but omitsroute53:GetChangeonarn:aws:route53:::change/*.The AWS Terraform provider polls
GetChangewhile waiting for a new record to reachINSYNCafter creation. Without the permission, scopes that create DNS records fail withAccessDeniedafter the record is already in the console — a confusing failure mode where the change visibly succeeds and then the deploy rolls back.This is a cross-scope footgun, not specific to
static-files— anything that writes DNS records through the provider hits it (k8s scopes withexternal-dns, frontend CloudFront distributions, anything with a CNAME/A).Found during a customer POC installing the
static-filesscope. Related downstream documentation PR: nullplatform/scopes-static-files#8.Change
One new statement added to
aws_iam_policy.nullplatform_route53_policy:{ "Sid" : "Route53GetChange", "Effect" : "Allow", "Action" : [ "route53:GetChange" ], "Resource" : [ "arn:aws:route53:::change/*" ] }Resource is
change/*(nothostedzone/*) —GetChangelives in a different ARN namespace. Style matches the existing Route 53 statement (jsonencode block, same indentation).Test plan
tofu fmt -recursivecleantofu init -backend=false && tofu test— 5/5 pass (route53_policy_naming,elb_policy_naming,eks_policy_naming,avp_policy_naming,all_policies_valid_json)start-initialfor a scope that creates a DNS record (e.g. static-files); confirm deploy reachesfinalizedwithoutAccessDeniedonGetChange.🤖 Generated with Claude Code