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 policyAmazonEC2ContainerRegistryFullAccess
)
{
"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
- aws-actions/configure-aws-credentials
- aws-actions/amazon-ecr-login
- docker/login-action
- docker/build-push-action
References
- OIDC for Git Action
- How OpenID Connect Works
- Use IAM roles to connect GitHub Actions to actions in AWS
- Configuring OpenID Connect in Amazon Web Services
- About security hardening with OpenID Connect
comments powered by Disqus