AAWSLearn
Back to Blog
DevOps11 min read

CI/CD with GitHub Actions and AWS

Build a complete deployment pipeline using GitHub Actions, OIDC federation, and AWS CodeDeploy or ECS.

#CI/CD#GitHub Actions#AWS

Hardcoding permanent AWS IAM Access Keys inside your GitHub repository secrets is a significant security risk. If those keys are leaked, attackers gain instant access to your cloud account.

The modern standard is using OpenID Connect (OIDC) federation, which allows GitHub Actions workflows to request short-lived, temporary security credentials directly from AWS.


1. Configure the IAM OIDC Provider

First, register GitHub as an identity provider (IdP) in your AWS account. Then, create an IAM role with a trust policy that permits GitHub to assume it:

{
  "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"
        },
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:awslearn/awslearnai:*"
        }
      }
    }
  ]
}

2. The GitHub Actions Workflow

Below is a complete GitHub Actions YAML workflow configuration. It authenticates with AWS via OIDC and deploys a zip artifact to Amazon S3:

name: Deploy to AWS Production
on:
  push:
    branches:
      - main

permissions:
  id-token: write # Required for requesting the JWT OIDC token
  contents: read  # Required for checkout

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GithubActionsOIDCDeployRole
          aws-region: us-east-1

      - name: Deploy Build Artifact to S3
        run: |
          aws s3 sync ./public s3://awslearn-production-web-bucket/ --delete

Using this setup, no permanent secrets exist in your GitHub repo, and the credentials assumed by the runner automatically expire after 1 hour, minimizing attack surface drastically.

Related Articles

DevOps

Terraform Modules: Best Practices for Production

Structure reusable Terraform modules with proper state management, versioning, and CI/CD integration.

Architecture

AWS Well-Architected Framework: A Practical Guide

Learn the six pillars of the Well-Architected Framework and how to apply them to real-world cloud workloads.

Kubernetes

EKS Production Checklist: From Cluster to Deployment

A comprehensive checklist for running production-grade Kubernetes on Amazon EKS with security and observability.

Search AWSLearn

Search for AWS VPC, Karpenter, Docker builds, Linux runlevels, or Terraform states.