{"id":528,"date":"2025-05-15T11:30:35","date_gmt":"2025-05-15T11:30:35","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=528"},"modified":"2025-05-15T11:30:35","modified_gmt":"2025-05-15T11:30:35","slug":"github-actions-oidc-aws","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=528","title":{"rendered":"How to Configure GitHub Actions OIDC with AWS (Easy Tutorial)"},"content":{"rendered":"<p>In this blog, we will look at GitHub\u202fActions OIDC AWS Integration using a step-by-step example that secures access to the AWS cloud.<\/p>\n<p>By the end of this guide, you\u2019ll understand:<\/p>\n<ul>\n<li>Why OIDC is a secure way to connect GitHub Actions with AWS<\/li>\n<li>How GitHub\u2019s OIDC integration works with AWS<\/li>\n<li>A step-by-step method to set up OIDC using IAM roles<\/li>\n<li>How to test the setup using AWS CLI and deploy to EKS with GitHub Actions workflows<\/li>\n<\/ul>\n<p>Lets gets started.<\/p>\n<h2 id=\"sample-aws-deployment-workflow-with-github-actions\">Sample AWS Deployment Workflow With GitHub Actions<\/h2>\n<p>The following image gives you a context on how GitHub Actions interact with AWS services.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/ACTIONS-OIDC.png\" class=\"kg-image\" alt=\"Example AWS deployment with Github Actions workflow\" loading=\"lazy\" width=\"695\" height=\"801\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/ACTIONS-OIDC.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/ACTIONS-OIDC.png 695w\"><\/figure>\n<p>In the above workflow, we have used an example of GitHub actions workflow that interacts with AWS EKS to push images to ECR and deploy applications on EKS.<\/p>\n<h2 id=\"understanding-aws-authentication-methods-for-github-actions\">Understanding AWS Authentication Methods for GitHub Actions<\/h2>\n<p>For the GitHub actions to interact with AWS services, it needs to authenticate with AWS. <\/p>\n<p>Let&#8217;s look at the different ways you can access AWS services like an EKS cluster from GitHub Actions. This way you understand why OpenID Connect is secure than other methods.<\/p>\n<h3 id=\"1-access-keys-and-secret-keys\">1. Access Keys And Secret Keys <\/h3>\n<p>The basic way to access EKS clusters from actions is by using AWS access and secret keys. <\/p>\n<p>Here is an example workflow configuration.<\/p>\n<pre><code class=\"language-bash\">- name: Configure AWS credentials\n  uses: aws-actions\/configure-aws-credentials@v1\n  with:\n    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    aws-region: us-west-2<\/code><\/pre>\n<p>But, storing or using AWS access and secret keys (long-lived tokens) directly in CI\/CD pipelines is considered insecure and not a recommended approach.<\/p>\n<p>If these long-term credentials are leaked, anyone with access to them can potentially control your AWS resources, leading to data breaches or infrastructure compromise.<\/p>\n<h3 id=\"2-for-self-hosted-runners-using-iam-roles\">2. For Self-Hosted Runners: Using IAM Roles<\/h3>\n<p>The recommended approach to overcome the limitations of using access keys and secrets is <a href=\"https:\/\/devopscube.com\/aws-iam-role-instance-profile\/\" rel=\"noreferrer\">AWS IAM roles<\/a>.  <\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">IAM roles can only be applied to the <a href=\"https:\/\/devopscube.com\/github-actions-self-hosted-runner\/\" rel=\"noreferrer\">Github actions self-hosted runners<\/a> running on AWS environment. You cannot use it with Github hosted public runners.<\/div>\n<\/div>\n<p>IAM roles use Temporary security credentials. It is not stored with the user but are created dynamically and given to the user when needed. They can be set to last from a few minutes to several hours. <\/p>\n<p>Once they expire, AWS no longer recognizes them or allows access through API requests made with them.<\/p>\n<h3 id=\"3-openid-connect-a-secure-approach\">3. OpenID Connect (A Secure Approach)<\/h3>\n<p>OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in AWS without needing to store AWS credentials as long-lived GitHub secrets. <\/p>\n<p>This means that a GitHub Actions workflow can request a short\u2011lived OIDC token from GitHub, present it to AWS IAM, and get a temporary role. There is no need to store access keys in secrets.<\/p>\n<p>Also, temporary credentials do not exist until a workflow needs them, and they expire shortly after (zero standing permissions).<\/p>\n<blockquote><p>OIDC can be used for both Github hosted runners and self-hosted runners.<\/p><\/blockquote>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\"><a href=\"https:\/\/openid.net\/?ref=devopscube.com\" rel=\"noreferrer\">OpenID<\/a> Connect adds an identity layer on top of <a href=\"https:\/\/oauth.net\/2\/?ref=devopscube.com\" rel=\"noreferrer\">OAuth 2.0<\/a>, which is primarily an authorization framework. While OAuth 2.0 focuses on granting applications access to specific resources, OIDC specifically handles authentication and identity verification.<\/div>\n<\/div>\n<p>In this guide, our focus is only on the OpenID Connect based GitHub actions workflow with AWS.<\/p>\n<h2 id=\"configuring-github-actions-oidc-with-aws-iam\">Configuring GitHub Actions OIDC with AWS IAM<\/h2>\n<p>Now, let&#8217;s look at a practical example, where I show you step by step how to configure OIDC with GitHub and AWS.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">This is the One-Time Setup<\/div>\n<\/div>\n<h3 id=\"step-1-create-the-oidc-identity-provider-in-aws-iam-for-github\">Step 1: Create the OIDC Identity Provider in AWS IAM for GitHub<\/h3>\n<p>In this setup, GitHub is the OpenID\u202fProvider. So we need to setup the provider details on AWS. <\/p>\n<p>Navigate to AWS IAM \u2192 Identity Providers.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-14.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1384\" height=\"952\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-14.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/05\/image-14.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-14.png 1384w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Add a new provider:<\/p>\n<ul>\n<ul>\n<li><strong>Provider type:<\/strong>&nbsp;OpenID Connect<\/li>\n<li><strong>Provider URL:<\/strong><code>https:\/\/token.actions.githubusercontent.com<\/code><\/li>\n<li><strong>Audience:<\/strong><code>sts.amazonaws.com<\/code><\/li>\n<\/ul>\n<\/ul>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-19.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"702\" height=\"521\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-19.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-19.png 702w\"><\/figure>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">This step tells AWS to trust tokens issued by GitHub Actions. Basically we are establishing a trust relationship between Github and AWS<\/div>\n<\/div>\n<h3 id=\"step-2-create-webidentity-iam-role-with-trust-policy\">Step 2: Create WebIdentity IAM Role with Trust Policy<\/h3>\n<p>If you <strong>click the created Identity provider<\/strong>, you will get an option to <strong>Assign role <\/strong>as shown below. <\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-46.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"995\" height=\"590\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-46.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-46.png 995w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Click <strong>Assign role <\/strong>and select the create a new role option.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-47.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"661\" height=\"330\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-47.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-47.png 661w\"><\/figure>\n<p>Next, select the trusted entity type &#8220;<strong>Web Identity<\/strong>&#8221; to log in to AWS with OIDC. <\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">A <i><em class=\"italic\" style=\"white-space: pre-wrap;\">web identity<\/em><\/i> in AWS IAM means <i><em class=\"italic\" style=\"white-space: pre-wrap;\">a service or user outside AWS will sign in with an OIDC token<\/em><\/i>.<\/div>\n<\/div>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-20.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"827\" height=\"501\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-20.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-20.png 827w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now, enter the web identity information. Under Github Organization, enter your Github organization ID. <\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">There is where you configure which organizations, repositories or branches that are allowed to assume the role.<\/div>\n<\/div>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-21.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"696\" height=\"596\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-21.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-21.png 696w\"><\/figure>\n<p>Next, add IAM permissions. Here, I am adding admin permissions. But as per your requirements and use cases, you can add only the required IAM permissions that your runner needs.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-22.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"608\" height=\"440\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-22.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-22.png 608w\"><\/figure>\n<p>In the next page, enter the role name (eg, <code>github-actions-workflow-role<\/code>), review the details and click create role.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">This is the IAM Role that your GitHub Actions workflow can assume. It definines what the workflow is allowed to do in your AWS account<\/div>\n<\/div>\n<h3 id=\"step-3-add-the-iam-role-arn-to-github\">Step 3: Add the IAM Role arn to Github<\/h3>\n<p>Now you need to add the role ARN to GitHub\u202fSecrets.<\/p>\n<p>You have two choices:<\/p>\n<ol>\n<li><strong>Organization secret: <\/strong>Available to all repositories in the organization.<\/li>\n<li><strong>Repository secret:<\/strong> Available only to one repository.<\/li>\n<\/ol>\n<p>Pick the option that fits your needs. For this demo, we\u2019ll set the secret at the organization level.<\/p>\n<p>Navigate to the org or repo settings.<\/p>\n<p>In the left pane you will find the secrets and variables option. Under secrets and variables, choose actions.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-18.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"460\" height=\"291\"><\/figure>\n<\/p>\n<p>AWS_OIDC_ROLE<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-23.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"492\" height=\"543\"><\/figure>\n<h3 id=\"step-4-testing-the-oidc-connection-to-aws\">Step 4: Testing the OIDC Connection to AWS<\/h3>\n<p>The next step is to validate the integration of OIDC with AWS.<\/p>\n<p>The following action uses the <code>aws-actions\/configure-aws-credentials<\/code> action to configure OIDC in workflows. <code>secrets.AWS_OIDC_ROLE<\/code> fetches the secret arn we created in the previous step.<\/p>\n<pre><code>- name: Configure AWS credentials using OIDC\n  uses: aws-actions\/configure-aws-credentials@v4\n  with:\n    role-to-assume: ${{ secrets.AWS_OIDC_ROLE }}\n    aws-region: us-west-2<\/code><\/pre>\n<p>To test this, we will create a simple GitHub Actions working to list AWS instances.<\/p>\n<p>Create a <code>ec2-list.yaml<\/code> workflow file in your repository and copy the following workflow.<\/p>\n<pre><code class=\"language-bash\">name: List EC2 Instances\n\non:\n  push:\n    branches:\n      - main\n\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  list-ec2:\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout repository\n      uses: actions\/checkout@v3\n\n    - name: Configure AWS credentials using OIDC\n      uses: aws-actions\/configure-aws-credentials@v4\n      with:\n        role-to-assume: ${{ secrets.AWS_OIDC_ROLE }}\n        aws-region: us-west-2\n\n    - name: List EC2 Instances\n      run: |\n        aws ec2 describe-instances \\\n          --query \"Reservations[*].Instances[*].InstanceId\" \\\n          --output table\n<\/code><\/pre>\n<p>If all the configurations are correct, when you run the workflow, you should be able to see the successful output as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-24.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"594\" height=\"591\"><\/figure>\n<p>Now that we have validated the OIDC AWS access using a workflow, we will test an EKS-based deployment using a workflow.<\/p>\n<h3 id=\"step-5-enabling-github-actions-access-to-amazon-eks-via-oidc\">Step 5: Enabling GitHub Actions Access to Amazon EKS via OIDC<\/h3>\n<p>When setting up GitHub Actions to access an EKS cluster, you need to take several specific steps beyond basic AWS authentication. <\/p>\n<p>This is because accessing an EKS cluster requires both AWS IAM permissions and Kubernetes-specific RBAC settings.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">Ensure you have the latest AWS CLI installed to execute the following command. If you have a old cli, please upgrade it to the latest one.<\/div>\n<\/div>\n<pre><code class=\"language-bash\">aws eks create-access-entry \\\n    --cluster-name &lt;your-cluster-name&gt; \\\n    --principal-arn &lt;your-role-arn-here&gt;\n    --kubernetes-groups github-runners \\\n    --type STANDARD \\\n    --username github-actions-oidc<\/code><\/pre>\n<p>Next, we set up access policies for the arn to access Kubernetes objects.<\/p>\n<p>You can list the available access polices using the following command.<\/p>\n<pre><code class=\"language-bash\">aws eks list-access-policies --output table<\/code><\/pre>\n<p>Most runners would admin policy to deploy and manage the clusters. So, for testing purposes, I am going to assign AmazonEKSAdminPolicy <\/p>\n<pre><code class=\"language-bash\">  aws eks associate-access-policy \\\n  --cluster-name &lt;your-cluster-name&gt; \\\n  --principal-arn &lt;your-role-arn-here&gt; \\\n  --policy-arn arn:aws:eks::aws:cluster-access-policy\/AmazonEKSViewPolicy \\\n  --access-scope type=cluster<\/code><\/pre>\n<h2 id=\"step-6-test-the-eks-workflow\">Step 6: Test The EKS Workflow<\/h2>\n<ul>\n<li>GitHub Actions requests an OIDC token from its OIDC provider.<\/li>\n<li>The token is presented to AWS STS (AssumeRoleWithWebIdentity).<\/li>\n<li>AWS validates the token and issues short-lived credentials for the IAM role.<\/li>\n<li>The workflow uses these credentials to access AWS resources.<\/li>\n<\/ul>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/cdn.hashnode.com\/res\/hashnode\/image\/upload\/v1745351829696\/da7a47f6-ef88-42fe-9dd2-9722d9b52750.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"844\" height=\"351\"><\/figure>\n<p>Here is an example of a GitHub Actions workflow that implements OIDC for AWS. I have used the <code>workflow_dispatch<\/code> trigger to deploy the workflow manually from the GitHub UI.<\/p>\n<pre><code class=\"language-bash\">name: Deploy NGINX to EKS\n\non:\n  workflow_dispatch:\n\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout repository\n      uses: actions\/checkout@v3\n\n    - name: Configure AWS credentials using OIDC\n      uses: aws-actions\/configure-aws-credentials@v4\n      with:\n        role-to-assume: ${{ secrets.AWS_OIDC_ROLE }}\n        aws-region: us-west-2\n\n    - name: Set up kubeconfig\n      run: |\n        aws eks update-kubeconfig --region us-west-2 --name eks-spot-cluster-bibin\n\n    - name: Deploy NGINX to EKS\n      run: |\n        kubectl create deployment nginx --image=nginx --port=80 --dry-run=client -o yaml | kubectl apply -f -<\/code><\/pre>\n<p>In the above workflow, update the Role URL and cluster name before running it.<\/p>\n<p>If you trigger the workflow manually, you will see the successful output as shown below. <\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-44.png\" class=\"kg-image\" alt=\"GitHub OIDC AWS workflow\" loading=\"lazy\" width=\"673\" height=\"488\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-44.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-44.png 673w\"><\/figure>\n<h2 id=\"openid-connect-workflow\">OpenID Connect Workflow<\/h2>\n<p>Now that we have done the hands-on, let&#8217;s look at the whole workflow. It will make more sense to you now.<\/p>\n<p>The following image shows the end-to-end workflow.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/actions-oidc-aws-1.png\" class=\"kg-image\" alt=\"GitHub Actions OIDC AWS detailed Workflow\" loading=\"lazy\" width=\"770\" height=\"987\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/actions-oidc-aws-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/actions-oidc-aws-1.png 770w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Here is how it works.<\/p>\n<ul>\n<li>In AWS, as a one-time task, we establish an OIDC trust between AWS and the GitHub workflows by creating an OIDC Identity Provider with a relevant IAM role to assume.<\/li>\n<li>Behind the scenes, the <code>aws-actions\/configure-aws-credentials<\/code> action makes a request to GitHub&#8217;s OIDC provider for a JWT token.<\/li>\n<li>It then takes this OIDC token and makes a call to the AWS Security Token Service. AWS then verifies the token and details with the entries configured in the IAM OIDC provider<\/li>\n<li>Once validated, AWS STS generates temporary short-lived (defaults to 1 hr) AWS security credentials. However, you can configure it to have ranges from <strong>15 mins to 12 hours.<\/strong><\/li>\n<li>Then <code>aws-actions\/configure-aws-credentials<\/code> action exposes these credentials as environment variables (e.g., <code>AWS_ACCESS_KEY_ID<\/code>, <code>AWS_SECRET_ACCESS_KEY<\/code>, <code>AWS_SESSION_TOKEN<\/code>)<\/li>\n<li>Now, in your workflow, when you use <a href=\"https:\/\/devopscube.com\/install-configure-aws-cli-linux\/\" rel=\"noreferrer\">AWS CLI<\/a> or an SDK like boto3, it makes use of the credentials in the environment variables.<\/li>\n<\/ul>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\u2753<\/div>\n<div class=\"kg-callout-text\">So what happens to the temporary credentials if the workflow finishes soon and the runner gets deleted?<\/p>\n<p>If the temporary token is valid for 1 hour and if GitHub Actions job finishes in 10 minutes, the temporary AWS credentials it obtained will still be technically valid for the remaining 50 minutes.<\/p><\/div>\n<\/div>\n<h2 id=\"configuring-oidc-for-aws-with-self-hosted-github-enterprise-server-ghes\">Configuring OIDC for AWS with Self-Hosted GitHub Enterprise Server (GHES)<\/h2>\n<p>You can also setup OIDC with self-hosted GitHub Enterprise servers.<\/p>\n<p>When when working with GHES OIDC you need to consider the following.<\/p>\n<ol>\n<li>The issuer URL will be your GHES hostname. For example, <code>https:\/\/&lt;GHES_HOSTNAME&gt;\/_services\/token<\/code><\/li>\n<li>The GHES instance&#8217;s OIDC endpoint must be publicly accessible over HTTPS or allowed access to AWS IP ranges. <\/li>\n<\/ol>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">A fully private GHES cannot work with AWS OIDC becuase AWS needs to fetch the OIDC issuer&#8217;s metadata from your GHES instance<\/div>\n<\/div>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Securing your CI\/CD pipelines is an important aspect of modern software development, especially when deploying applications to cloud environments like AWS. <\/p>\n<p>By leveraging GitHub Actions OIDC for AWS, you can enhance the security of your workflows without the need for long-lived AWS credentials. <\/p>\n<p>This approach not only mitigates the risks associated with access keys and secrets but also simplifies credential management through the use of temporary security credentials. <\/p>\n<p>Now we would like to hear from you.<\/p>\n<p>How do you manage credentials for AWS access through Github Actions?<\/p>\n<p>Have you tried OIDC approach?<\/p>\n<p>Do let us know in the comments.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/github-actions-oidc-aws\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Configure GitHub Actions OIDC with AWS (Easy Tutorial) \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/github-actions-oidc-aws\/<\/p>\n","protected":false},"author":1,"featured_media":529,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-528","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=528"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/528\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/529"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}