BuildNot yet confirmed elsewhere1 publisher2 min readPublished
Dropping long-lived AWS keys is half an EKS migration; the cluster still gets a vote
A clean STS exchange proves only that IAM let the job in. EKS authorizes separately, and that is the half of the migration most walkthroughs skip.
The Engineer · Build desk
What happened
- The pipeline's first version kept AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in repository settings, and the author says they worked.
- The replacement: GitHub mints a per-job token, STS checks its signature against a registered provider and its claims against the role's trust policy.
- The workflow side is small: id-token write permission, contents read, and configure-aws-credentials v4 with a role ARN, a session name and a region.
- AWS now verifies and rotates the provider certificate itself, so the old thumbprint value only matters for tooling that still insists on one.
Why it matters
- constraint A successful credentials step can no longer serve as the deploy gate, because the permission that decides the outcome sits outside anything an IAM policy review reads.
- exposure A sub pattern one character wider than intended promotes everyone who can open a pull request into a deployer, and IAM will consider that correct.
- cost Standing keys look cheap because their maintenance bill is deferred: rotation cost grows with every repository holding the key, so it gets paid only after a leak.
- decision One role for build and deploy becomes hard to defend once you have to argue why a build step should be able to reach the cluster at all.
Two systems get a vote here, and only one of them leaves a trace where you are looking. The deploy role in this setup carries a single IAM action, eks:DescribeCluster against one cluster ARN [15]. That is enough to fetch an endpoint and write a kubeconfig. So the run collects its temporary credentials, writes the file, and then the cluster forms an opinion of its own, because EKS layers authorization above IAM [1].
The author is direct about that being the step that broke and the step tutorials leave out [1]. The text supplied to us stops mid-command at the update-kubeconfig line [3], so the cluster-side grant itself is not on the page, and I am not going to invent one. What travels anyway is the shape of the problem: an identity that authenticates perfectly can still be a stranger to the thing it is trying to change.
The permission arithmetic is worth copying. A job that also pushes images needs six ECR actions [16]. Fold build and deploy into one role and that role holds seven actions across two services [18]; keep them apart, as the author does, and a compromised build stage has no route to the cluster at all [17].
There are three enforcement points, and each is blind to the other two. IAM decides which jobs may assume the role, GitHub decides who may trigger those jobs (the author uses environments with a required reviewer for production) [14], and EKS decides whether the resulting identity may touch a resource [1]. A migration that only touches the first will pass every check the first is capable of performing.
The credential story does improve. An access key never expires and stays valid after a leak until somebody revokes it [6], and its blast radius takes in forks and any third-party action the workflow pulls [7]. The OIDC exchange returns credentials that die with the job [8], a lifetime cut from unbounded to one run [19]. What replaces the key is not nothing, though: it is a piece of cluster state that has to exist, that no IAM policy review will miss, and that aws sts get-caller-identity will happily not mention.
Which sets the acceptance test. The only run that proves this migration landed is one where the deploy role, from CI, asks the cluster for something and gets an answer back. Anything short of that tests AWS authentication, which was never the part in doubt.
What to watch
- Whether the rest of the walkthrough shows how the cluster-side grant for the deploy role is created, and whether that step is automated or done once by hand.
- Whether the two-role split holds up once a build stage needs to read cluster state, for smoke tests or migrations, and quietly acquires cluster access.
- Any change to the sub claim patterns GitHub emits, which would either widen or break trust policies written against the current form.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence46
- Adoption16
- Hype gap+9
- Incentives27
- Confidence48
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
The author states that getting past IAM is only half the job because EKS has its own authorization layer on top of IAM, and that this is the part that broke for him and that most tutorials skip.
- [2]
The workflow sets permissions id-token: write and contents: read, and uses aws-actions/configure-aws-credentials@v4 with a role-to-assume ARN, a role-session-name of gha-deploy-${{ github.run_id }} and aws-region ap-south-1.
- [3]
The supplied source text ends mid-command at "aws eks upd" in the Update kubeconfig step, so no cluster-side authorization configuration is shown in the material provided.
- [4]
The author built a 3-tier application on Amazon EKS, deployed by a GitHub Actions pipeline that runs on every merge to main.
- [5]
The first version of the pipeline had two secrets in the repository settings, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY; the author says they worked and were a bad idea.
- [6]
An IAM access key does not expire; if it leaks it stays valid until someone notices and revokes it.
- [7]
A fork or a compromised third-party action widens the blast radius of a key stored in repository settings.
- [8]
OIDC replaces the stored key with a token that lives for the length of a single job, and STS returns temporary credentials that expire when the job ends.
- [9]
The flow has four steps: GitHub Actions mints a short-lived JWT describing repo, branch and workflow; the workflow sends it to AWS STS; AWS checks the token signature against a registered identity provider and then the claims against the IAM role's trust policy; STS returns temporary credentials.
- [10]
The OIDC provider is created once per AWS account using aws iam create-open-id-connect-provider with url https://token.actions.githubusercontent.com and client-id-list sts.amazonaws.com.
- [11]
AWS no longer requires managing a certificate thumbprint for this provider and verifies and rotates the certificate itself; older guides use 6938fd4d98bab03faadb97b34396831e3780aea1 for tooling that still demands a value.
- [12]
The trust policy allows sts:AssumeRoleWithWebIdentity with a StringEquals condition on the aud claim equal to sts.amazonaws.com and a StringLike condition on the sub claim, shown as repo:my-org/my-repo:ref:refs/heads/main.
- [13]
The author says the sub condition is the only thing standing between "my main branch can deploy" and "anyone who opens a pull request against my repo can deploy".
- [14]
The author uses the environment form of the sub condition for production because GitHub environments allow a required reviewer; IAM enforces which jobs can assume the role and GitHub enforces who can trigger those jobs.
- [15]
The deploy role's permission policy grants a single action, eks:DescribeCluster, on one cluster ARN, described as enough to look up the cluster endpoint.
- [16]
If the same job also pushes images it needs six ECR actions: GetAuthorizationToken, BatchCheckLayerAvailability, PutImage, InitiateLayerUpload, UploadLayerPart and CompleteLayerUpload.
- [17]
The author prefers two separate roles, one for build and push and one for deploy, so that a compromised build step cannot touch the cluster.
- [18]
A single role covering both build-and-push and deploy would hold seven API actions across two AWS services, against one action for a deploy-only role.
- [19]
The migration reduces credential lifetime from unbounded to the duration of a single CI job.
- [20]
Rotating a stored key means updating every repository that uses it, so in practice nobody rotates it.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.to3 Tier Application On EKS
1 article · August 22, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.
Topics
Entities
- Amazon EKSFollow
- GitHub ActionsFollow
- AWS IAMFollow
- AWS STSFollow
- Amazon Elastic Container RegistryFollow
- aws-actions/configure-aws-credentialsFollow
- OpenID ConnectFollow
- Kubernetes RBACFollow
- EKS Access EntriesFollow
- kubectlFollow