GitHub Actions to AWS Without Long-Lived Keys
Use GitHub OIDC, a tightly scoped IAM trust policy, and deployment checks to replace stored AWS access keys with short-lived credentials. Includes a trust-policy example and a safe validation plan.
A GitHub Actions workflow often needs AWS access to publish an artifact, update infrastructure, or deploy an application. A stored access key can work, but it creates a secret that must be protected, rotated, and removed when its scope changes. OpenID Connect (OIDC) lets a workflow request short-lived AWS credentials for a specific job instead.
This pattern has three parts: a GitHub OIDC identity provider in AWS, an IAM role whose trust policy matches the intended repository and deployment context, and a permissions policy that grants only the actions and resources the job needs.
1. Scope the role to one workflow identity
For a branch-based deployment from the main branch, an example trust policy is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:YOUR_ORG/YOUR_REPO:ref:refs/heads/main"
}
}
}]
}Replace the account, organization, and repository placeholders. Keep the audience check and restrict the subject (sub) to the intended repository and branch. A wildcard-only subject is too broad. If you deploy through a GitHub environment, its subject format is different; set the trust condition to that environment identity and use GitHub required reviewers or protection rules for production.
2. Request an identity token only in the deployment job
Give the job the minimum GitHub token permissions it needs. For a job that checks out source and requests OIDC, a common starting point is:
1
2
3
permissions:
contents: read
id-token: writeKeep id-token: write scoped to the deployment job instead of granting it to every job. Configure the AWS credentials action to assume the role, and avoid saving AWS access keys in repository or organization secrets.
3. Limit what the role can change
The role permissions policy is separate from its trust policy. Trust decides who may assume the role; permissions decide what the role may do. Scope actions to the deployment's exact resources where possible. For example, a static-site job might write only to one S3 bucket prefix and invalidate one CloudFront distribution. Use separate roles for test and production so a test workflow cannot deploy to production.
4. Test both the allowed and denied paths
First run the workflow from the approved branch and confirm it gets temporary credentials. Then try a feature branch or an untrusted pull request and confirm it cannot assume the production role. Review CloudTrail for AssumeRoleWithWebIdentity events and alert on unexpected repositories or role sessions. If the subject condition is wrong, the job fails at role assumption; that is useful fail-closed behavior, but it can interrupt deployments until the GitHub context and trust policy match again.
OIDC removes a long-lived AWS key from GitHub secrets, but it does not make a workflow inherently safe. Protect workflow files, pin third-party actions to reviewed versions, restrict production environments, and keep the IAM permissions small. AWS IAM guidance recommends temporary credentials and least privilege; its OIDC role setup guidance explains the required GitHub aud and sub conditions.
References:
- AWS IAM: Create a role for OpenID Connect federation — https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
- AWS IAM: Security best practices — https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article