Integrating GitHub Actions with AWS Using OIDC authentication

Integrating GitHub Actions with AWS Using OIDC authentication

avatar

Phong Nguyen

2024.08.09

Giới thiệu về OIDC, cơ chế hoạt động và Demo áp dụng - Deploy multi lambda lên AWS Account tương ứng cho từng môi trường sử dụng GitHub Action

Giới thiệu

Dự án của mình hiện tại sử dụng GitHub để quản lý source code và môi trường AWS để vận hành hạ tầng.

Khi sử dụng GitHub thì dự án mình cũng có sử dụng Github Action cho một số mục đích như một phần trong chu trình CICD

  • Scan Vulnerabilities Docker image
  • Check golang lint
  • Build Docker image, push to ECR
  • Deploy Lambda
  • Deploy Bastion host
  • v.v

Để liên kết giữa GitHub Action và AWS, trước đây dự án mình dùng IAM User Access Key, tuy nhiên dùng long-term credentials không được khuyến khích nên mình đã chuyển sang dùng OIDC Authentication.

Bài viết này nhằm giới thiệu về OIDC và một bài Demo nhỏ - Deploy Multi lambda sử dụng GitHub Action

OIDC là gì?

OpenID Connect (OIDC) là giao thức xác thực người dùng dựa trên OAuth 2.0.

OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Amazon Web Services (AWS), without needing to store the AWS credentials as long-lived GitHub secrets.

Các ứng dụng của bên thứ ba xác thực người dùng thông qua OIDC và trao đổi thông tin người dùng một cách an toàn bằng cách sử dụng JWT (JSON Web Token). Nó cung cấp xác thực an toàn và linh hoạt hơn so với các phương thức xác thực khác.

Tại sao nên sử dụng OIDC?

Trước đây dự án mình sử dụng IAM User Access key và Secret key, lưu các giá trị này trong Secret của Github và sử dụng để liên kết với AWS

Setting:

Github workflow

# Ref. https://github.com/aws-actions/configure-aws-credentials
- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_DEV }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }}
    aws-region: us-east-1

Các biến này được mã hóa vì chúng được lưu dưới dạng Secret. Nhưng có một vấn đề là những thông tin này lưu ở bên ngoài AWS dưới dạng long-term credentials, và các vấn đề về rotation hay nguy cơ rò rỉ.

Mặt khác, nếu chuyển sang phương thức xác thực OIDC, bạn sẽ sử dụng temporary credentials gắn với IAM Role khi truy cập tài nguyên AWS từ workflow của GitHub Actions. Thông tin này là ngắn hạn nên ngay cả khi chúng bị lộ, rủi ro cũng sẽ thấp hơn.

Authentication Flow

Architecture Diagram

Diagram bên dưới thể hiện mối quan hệ khi sử dụng GitHub Actions để truy cập vào môi trường AWS thông qua OIDC Authentication.

Flow thực thi

  1. Chuẩn bị GitHub OIDC provider phía AWS Account
  2. Chuẩn bị IAM Role dùng cho Github Repo đã Trust với GitHub OIDC provider
  3. Chỉ định Assume Role tại workflow của GitHub Actions

1. Tạo OICD Provider

Hướng dẫn này mình sử sụng Console để thực hiện:

Tại IAM Console -> Identity providers -> Add provider

Configure provider

  • Provider type: OpenID Connect
  • Provider URL: https:// token.actions.githubusercontent.com
  • Audience: sts.amazonaws.com

2. Create IAM Role dùng để Xác thực thông qua OIDC

  • Role name: CMPGitHubActionsRole
  • Permissions policies (Bài demo bên dưới mình sẽ sử dụng các policy sau)
    • AmazonS3FullAccess
    • AWSCloudFormationFullAccess
    • AWSLambda_FullAccess
    • CloudWatchLogsFullAccess
  • Trust relationships (mình muốn IAM Role này trust chỉ những git repo của mình)
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::067057696393:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": [
                        "repo:cloudmentor-pro/*"
                    ]
                }
            }
        }
    ]
}

Bạn có thể cho phép toàn bộ repo, một vài repo hoặc trên các branh cụ thể

Case 1: Cho phép toàn bộ branch trên 1 repo cụ thể

          StringLike:
            token.actions.githubusercontent.com:sub:
              - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/*'

Use-Case 2: Cho phép các branch có tiền tố cụ thể trong repo cụ thể

            StringLike:
              token.actions.githubusercontent.com:sub:
                - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/prefix-*'

Use-case 3: Cho phép nhiều branch cho một repo cụ thể

          ForAnyValue:StringLike:
            token.actions.githubusercontent.com:sub:
              - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/develop'
              - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/feature'

Use-case 4: Cho phép nhiều branch cho một repo cụ thể và cũng cho phép các workflow được kích hoạt bởi pull_request

          ForAnyValue:StringLike:
            token.actions.githubusercontent.com:sub:
              - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/develop'
              - 'repo:<GitHub username>/<GitHub repo name>:ref:refs/heads/feature'
              - 'repo:<GitHub username>/<GitHub repo name>:pull_request'

3. Setting Github Action Workflow

Để Xác thực truy cập đến AWS từ Github Action, chúng ta sẽ sử dụng Action: aws-actions/configure-aws-credentials

Ví dụ bên dưới cho workflow sử dụng GitHub Actions, Authen bằng OIDC, Login vào AWS Elastic Container Registry (ECR) và Build and push docker image lên ECR.

name: ECR Push Workflow

on:
  push:
    branches:
      - develop

jobs:
  deploy:
    name: Deploy to ECR
    runs-on: ubuntu-latest

    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: YOUR_AWS_REGION  # AWS Region setting
          role-to-assume: YOUR_OIDC_ROLE_ARN  # IAM Role Arn

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag, and push image to Amazon ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: YOUR_ECR_REPOSITORY_NAME  # ECR Repo name
          IMAGE_TAG: latest
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      # Other



Khi chúng ta merge code vào branch develop hoặc push code lên branch develop, Action này sẽ được kích hoạt.

Demo

Để ứng dụng OIDC, mình sẽ trích xuất 1 Use-case cụ thể trong trong dự án hiện tại: Deploy multi lambda fucntion sử dụng Github Action.

  • Demo này sẽ deploy những lambda fucntion nào có thay đổi source code. (Source lambda không thay đổi source code thì không deploy)
  • Có 3 môi trường: develop, staging, production tương tứng với các branch develop, staging, production
  • merge/push code lên branch develop sẽ Deploy lên AWS Account cho môi trường develop (staging và production cũng tương tự)
  • Lambda viết bằng go, sử dụng SAM để deploy
  • Github Action sẽ thực thi các SAM command

1. Chuẩn bị

  • Confirm đã tạo OICD Provider (phía trên)
  • Confirm đã tạo IAM Role cho GitHubAction (phía trên)
  • Fork Source Code and clone
  • Tạo S3 bucket: Tham khảo BUCKET_NAME trong Makefile (Source code)
  • Cập nhật Account ID của bạn trong file _go_lambda_deploy.yml

2. Test Github Action

  • Create branch develop
  • Change something like this
  • Push to develop branch

3. Confirm Action running

4. Confirm Lambda are created

Tài liệu tham khảo