Preface

Recently, I have been working to migrate our Jenkins pipeline to Github Actions. One of the part is to update the image we build to ECR. And we have compnay policy to avoid access key and secret key in anywhere. So we have to use Assume Role to access AWS service.

Create a OIDC provider in AWS IAM

First, we need to create a OIDC provider in AWS IAM. This is used to authenticate the role we assume.

  • IAM console -> Identity providers -> Create provider
  • For the provider URL:
    • If your company has a domain, you can use the domain name.
    https://HOSTNAME/_services/token
  • If you use GitHub cloud service, you can use the following URL.
    https://token.actions.githubusercontent.com
  • For the “Audience”: Use sts.amazonaws.com if you are using the official action.
    sts.amazonaws.com

Create a role in AWS IAM

  • Click Assign Role on OIDC provider page, or create a role in IAM console.
  • Scope the Trust Relationships to the OIDC provider you created in step 1.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::{aws-account-id}:oidc-provider/github.mycompany.com/_services/token"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "github.mycompany.com/_services/token:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "github.mycompany.com/_services/token:sub": "repo:myOrganization/*"
                }
            }
        }
    ]
}
  • Scope the Permissions to the ECR relate actions. (example is AWS managed policy AmazonEC2ContainerRegistryFullAccess)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:GetRepositoryPolicy",
                "ecr:DescribeRepositories",
                "ecr:ListImages",
                "ecr:DescribeImages",
                "ecr:BatchGetImage",
                "ecr:GetLifecyclePolicy",
                "ecr:GetLifecyclePolicyPreview",
                "ecr:ListTagsForResource",
                "ecr:DescribeImageScanFindings",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:PutImage"
            ],
            "Resource": "*"
        }
    ]
}

Create a GitHub Actions with following steps

name: example

on:
  workflow_dispatch:

env: 
  APP_ID: "example"
  NAMESPACE: "namespace"
  AWS_REGION: "us-west-2"

permissions:
  id-token: write   # This is required for requesting the JWT
  contents: read    # This is required for actions/checkout

jobs:
  build:
    environment: dev # if secrets is repo level, jobs have to dealer the environment name
    runs-on: ubuntu
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Configure aws credentials
        uses: aws-actions/configure-aws-credentials@v4.0.1
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          role-session-name: ${{ secrets.AWS_ROLE_SESSION_NAME }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Login to Amazon ECR
        uses: aws-actions/amazon-ecr-login@v2.0.1      

      - name: Build and push to ECR
        uses: docker/build-push-action@v5.0.0
        with:
          push: true
          tags: |
            ${{ secrets.ECR_HUB }}/${{ env.APP_ID }}:latest            
          file: Dockerfile

Uses github-action

References

comments powered by Disqus