GitHub Actions(GHA)からAWSリソースにアクセスしたいケースは業務上よくあると思います。
私のケースでは、GHAからAmazon ECRにアプリイメージをPUSHしたいケースがあり、その際にGHAからAWSの認証をどう通すかを検討する必要がありました。記事タイトルにある通り、GitHub OIDCプロバイダーという仕組みを利用することで手軽かつセキュアにアクセスさせることができたので、備忘のために記録します。
GitHub OIDCプロバイダーとは
GitHub OIDCプロバイダーとは、GitHubとAWSがOIDCを使って認証することでGHAのワークフローからAWSリソースにアクセスすることができるようになる仕組みです。AWS側に予めGHAワークフロー用のIAMロールを作っておくことで、GHAからキックされたOIDC認証フローを通すことが可能になります。シーケンス図にすると以下のようになります。
GitHub OIDCプロバイダーのメリットは以下の通りです。
- AWSアクセスキーとシークレットをGitHubのシークレットに渡す必要がない。GHAワークフロー用のIAMロールのARNだけ渡せば良い。
- AWSから払い出されるアクセストークンは有効期限付きであり短時間で期限切れになるように設定されている
1. GitHub OIDC用のIDプロバイダーを追加
まずはIAMからGitHub OIDC用のIDプロバイダーを追加します。
IAM>IDプロバイダ>プロバイダーを追加 から以下の画像の通りに追加します。
- URL: https://token.actions.githubusercontent.com
- 対象者: sts.amazonaws.com
2. IAMロールを作る
ここからは実際の手順を記載していきます。
まずはAWSコンソールからIAMロールの新規作成を実施し、信頼エンティティが以下になるように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::260475105314: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:{GitHub user or org name}/{GitHub repository name}:*"
]
}
}
}
]
}
3. GHAのシークレットにIAMロールのARNを渡す
先ほど作成したIAMロールのARNをGHAのシークレットに登録します。AWS_ROLE_ARNなどで登録し、GHAの設定ymlから参照できるようにしておきましょう。
以下はJavaアプリケーションをコンテナイメージにビルドしてAmazon ECRにPUSHする例です。
name: Build and Push to ECR
on:
push:
branches:
- main
workflow_dispatch:
env:
AWS_REGION: ap-northeast-1
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '25'
cache: 'gradle'
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Get current datetime
id: datetime
run: echo "datetime=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT
- name: Build image with bootBuildImage
working-directory: ./app/conex
run: |
./gradlew bootBuildImage \
--imageName=${{ secrets.ECR_REPOSITORY }}:conex_${{ steps.datetime.outputs.datetime }}
- name: Tag image as latest
run: |
docker tag ${{ secrets.ECR_REPOSITORY }}:conex_${{ steps.datetime.outputs.datetime }} ${{ secrets.ECR_REPOSITORY }}:latest
- name: Push image to Amazon ECR
run: |
docker push ${{ secrets.ECR_REPOSITORY }}:conex_${{ steps.datetime.outputs.datetime }}
docker push ${{ secrets.ECR_REPOSITORY }}:latest
- name: Output image tags
run: |
echo "Image pushed to ECR:"
echo "${{ secrets.ECR_REPOSITORY }}:conex_${{ steps.datetime.outputs.datetime }}"
echo "${{ secrets.ECR_REPOSITORY }}:latest"
以上!
