
Secure AWS Automation with GitHub Actions and OpenID Connect (OIDC)
Learn how to securely connect GitHub Actions to AWS without storing long-lived access keys. This practical guide explores OpenID Connect (OIDC), AWS IAM trust policies, AWS STS, temporary credentials, and least-privilege access using Terraform and GitHub Actions.
Series: Practical AWS Engineering: From Serverless to Cloud Architecture (2 articles)
- 2Secure AWS Automation with GitHub Actions and OpenID Connect (OIDC) This article
Secure AWS Automation with GitHub Actions and OpenID Connect (OIDC)
Level: Intermediate
Focus: AWS IAM, temporary credentials, OpenID Connect, GitHub Actions, least privilege.
Implementation status: This is a reference implementation. It has not been deployed or validated in a live AWS account. Validate the provider, trust policy, permissions, and workflow in a dedicated test environment before relying on it.
Introduction
CI/CD pipelines often need access to cloud resources: publishing an artifact, deploying an application, or updating infrastructure. A common shortcut is to create an IAM user's access key and store it as a CI/CD secret. These credentials are reusable until rotated or revoked. If exposed through a compromised runner, workflow, or accidental logging, they may be used outside the pipeline.
AWS supports a different pattern: a workload proves its identity using OpenID Connect (OIDC), then requests temporary AWS credentials for an IAM role. This article explains that pattern using GitHub Actions and AWS Security Token Service (AWS STS).
The objective is not just to remove access keys. It is to establish a narrowly scoped trust relationship between one repository/branch and one AWS role, then grant that role only the permissions the workflow needs.

Figure 1. GitHub Actions obtains a short-lived role session through OIDC instead of using a stored long-lived AWS access key.
1. Why long-lived access keys are risky
Static IAM user access keys can remain valid for a long time. They may be copied into workflows, developer machines, or secret stores. Rotation becomes an operational task, and every copy must be updated safely.
Common risks include accidental commits, credentials printed by workflows, compromised runners, keys remaining active after a project ends, and broad permissions increasing the impact of exposure.
Secret storage is important for credentials that must exist, but it does not change the fact that a static access key is reusable. Where workload federation is supported, short-lived credentials are usually a better fit.
2. The building blocks
Component | Responsibility |
|---|---|
GitHub Actions | Runs the automation workflow. |
GitHub OIDC issuer | Issues a signed identity token for the workflow context. |
AWS IAM OIDC provider | Establishes trust in the token issuer and audience. |
IAM role trust policy | Defines which federated identities may assume the role. |
AWS STS | Validates the token and issues temporary credentials. |
IAM permissions policy | Defines what the assumed role can do in AWS. |
Two policy types must be understood separately:
- Trust policy: Who can assume this role?
- Permissions policy: What can the role do after it is assumed?
A restrictive trust policy does not compensate for an overly broad permissions policy, and vice versa.
3. How the OIDC flow works

Figure 2. AWS validates the token issuer and audience, evaluates the role trust conditions, and STS issues a temporary session.
- A GitHub Actions job starts.
- The workflow is allowed to request an OIDC token by declaring
id-token: write.
- GitHub issues a signed token describing the workflow identity.
- The AWS credentials action presents the token to AWS STS using
AssumeRoleWithWebIdentity.
- AWS validates the token against the configured GitHub OIDC provider and evaluates the IAM role trust policy.
- If authorized, STS returns temporary credentials.
- The workflow uses those credentials to call permitted AWS APIs. The session expires according to the role session duration.
id-token: write permits the job to request an OIDC token; it does not itself grant AWS permissions. AWS authorization still depends on the role trust policy and attached permissions.4. Configure the GitHub OIDC provider in AWS
An IAM OIDC identity provider must exist in the AWS account before a role can trust it.
- Provider URL:
https://token.actions.githubusercontent.com
- Client ID (audience):
sts.amazonaws.com
Create the provider in IAM using the AWS Console or your approved infrastructure-as-code process. Confirm current AWS and GitHub documentation for provider setup and certificate/thumbprint handling rather than copying an old thumbprint from an example.
The Terraform example in this project accepts the ARN of an already-created GitHub OIDC provider as an input. This keeps provider lifecycle management separate from the example role. Do not create duplicate providers for the same issuer in one account; reuse an existing provider where appropriate.
5. Restrict the role trust policy
For a workflow running from the
main branch of one repository, the expected subject claim has this form:repo:OWNER/REPOSITORY:ref:refs/heads/main The Terraform example builds the subject from input variables and requires an exact match. It also checks that the audience is
sts.amazonaws.com .The trust policy should allow the configured GitHub OIDC provider as the federated principal, the
sts:AssumeRoleWithWebIdentity action, the expected audience, and the exact repository-and-branch subject.Avoid broad conditions such as
repo:OWNER/* unless every repository in that scope is intentionally trusted. A wildcard can allow an unintended repository to assume the role.Branches and GitHub Environments
The subject format changes when a workflow uses a GitHub Environment. The subject can identify the environment instead of the branch. If you add an environment such as
production , update the trust policy to match the exact subject format and configure environment protection rules. Do not copy a branch-based trust policy unchanged into an environment-based workflow.6. Grant only the permissions the workflow needs
The example role has a deliberately small read-only S3 policy for one bucket and the
reports/ prefix:-
s3:ListBucketon the specific bucket, constrained by thes3:prefixcondition.
-
s3:GetObjecton objects underreports/in that bucket.
It does not grant bucket creation, object writes, deletion, IAM administration, or access to every S3 bucket.
For a real pipeline, start with the exact API operations required. Scope resource ARNs wherever the service supports resource-level permissions. Some actions require
"Resource": "*" ; document why and consider applicable condition keys. Do not attach AdministratorAccess just to make a workflow succeed.7. Configure the GitHub Actions workflow
The sample workflow is in
.github/workflows/oidc-demo.yml . It runs on pushes to main and can also be started manually.Its important permissions are:
YAML
permissions:contents: readid-token: write
The workflow configures AWS credentials using a role ARN and Region, then runs:
Bash
aws sts get-caller-identity
This confirms which AWS identity the job is using. It then lists the approved S3 prefix as a permissions demonstration.
Store the role ARN and bucket name as GitHub Actions repository variables. The role ARN is an identifier, not a secret. The workflow must not contain an AWS access key ID or secret access key.
For production, pin third-party GitHub Actions to a reviewed full commit SHA rather than relying only on a mutable major-version tag. Review action updates through your normal dependency-management process.
8. Security considerations
OIDC reduces the need for long-lived credentials, but it does not make a pipeline automatically secure.
- Restrict the subject to the required repository and branch or protected environment.
- Protect the trusted branch with reviews and required status checks.
- Review workflow changes: someone who can modify a trusted workflow may change what the role does.
- Use least privilege for AWS actions and resources.
- Grant
id-token: writeonly to jobs that need federation.
- Protect sensitive environments with required reviewers and deployment rules.
- Pin third-party actions to reviewed immutable references.
- Never print tokens, credentials, or sensitive deployment output.
- Use CloudTrail to review role-assumption and API activity.
- Choose a session duration that is sufficient but not unnecessarily long.
A compromised workflow running in a trusted repository and branch may still obtain the role. OIDC establishes workload identity; repository governance and workflow security remain essential.
9. Troubleshooting
Symptom | Possible cause | What to check |
|---|---|---|
Not authorized to perform sts:AssumeRoleWithWebIdentity | Trust policy does not match token claims | Provider ARN, audience, exact sub condition. |
No OpenIDConnect provider found | Provider missing or ARN/issuer incorrect | Confirm provider exists in the same AWS account. |
Audience mismatch | Trust policy expects another audience | Confirm sts.amazonaws.com is configured. |
Subject mismatch | Branch, repository, or environment subject differs | Check workflow context and exact condition. |
S3 AccessDenied | Role assumed, but permissions are insufficient | Check attached policy, bucket policy, prefix, and organization controls. |
Workflow cannot request OIDC token | id-token: write missing or overridden | Check workflow/job permissions. |
Run
aws sts get-caller-identity after configuring credentials. If it succeeds, role assumption worked. An access-denied error on a later S3 command is a separate permissions issue.10. Cost considerations
OIDC federation does not require a continuously running compute service. However, AWS API usage and the resources your workflow operates can incur charges. GitHub Actions usage is subject to GitHub's plan and runner limits. Check current pricing and usage policies before scaling automation.
11. Validation checklist
This project has not yet been deployed or tested. In a dedicated non-production account:
- Confirm the GitHub OIDC provider exists in the intended AWS account.
- Review the Terraform plan and confirm the exact repository/branch subject.
- Apply only after reviewing the plan and permissions.
- Configure
AWS_ROLE_ARNandDEMO_BUCKETas GitHub repository variables.
- Trigger the workflow from the trusted
mainbranch.
- Confirm
aws sts get-caller-identityreports the expected assumed role.
- Confirm listing the allowed
reports/prefix succeeds.
- Confirm reading an object outside the allowed prefix is denied.
- Confirm an untrusted branch or repository cannot assume the role.
- Review CloudTrail events and remove test resources when finished.
Do not claim the workflow is working until these checks have actually been performed. Use a dedicated test bucket and non-sensitive sample objects.
12. When should you use this pattern?
Use OIDC federation when an external workload such as GitHub Actions needs AWS access and supports issuing a trusted identity token. Examples include CI pipelines that publish artifacts, deployment workflows, and infrastructure automation running Terraform against AWS.
The trust conditions and permissions should differ by workload. A build job that uploads an artifact should not automatically receive the same role as a production deployment job.
Conclusion
Long-lived access keys are not the only way for automation to authenticate to AWS. With OIDC federation, GitHub Actions can present a signed workload identity to AWS STS and receive temporary credentials for a narrowly scoped IAM role.
The strongest design combines a precise trust policy, least-privilege permissions, protected source branches, reviewed workflow changes, and CloudTrail visibility. OIDC reduces credential-management risk, but it does not replace secure CI/CD practices.
The central lesson is to treat the pipeline as an identity with a defined trust boundary: decide exactly which workload may assume the role, what it may do, and how its activity will be reviewed.
References
Author note before publication: Add a short explanation in your own voice about why you chose OIDC federation and what you learned about the difference between a role trust policy and a permissions policy. After completing the validation checklist, replace the implementation-status note with the actual tests performed and their results.
Series: Practical AWS Engineering: From Serverless to Cloud Architecture (2 articles)
- 2Secure AWS Automation with GitHub Actions and OpenID Connect (OIDC) This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article