GitHub ActionsにてOIDCを使ってECRへpush/S3へアップロードを行う!
はじめに
個人開発にてReact(s3)、Rails(ECS)の構成でアプリケーションを作成しており、CICDを作るにあたってGitHub Actionsではフロント側はs3へsync、バックエンドはコンテナイメージをpushしたい要件があり実際の作業内容を備忘録として記事にすることにしました。
また今回調べているとOIDC(OpenID Connect)という仕組みを使ってセキュアに実装できることがわかったためOIDCを利用することとしました。
そもそもOIDCとは
ChatGPTに聞いてみました
AWSにおけるOIDC(OpenID Connect)は、外部のアイデンティティプロバイダー(IdP)を利用して、AWSリソースへのアクセスを制御するための標準プロトコルです。OIDCは、OAuth 2.0の上に構築された認証レイヤーで、認証(ユーザーの識別)と認可(アクセス権の付与)の両方をサポートします。
OIDCの概要
認証プロトコル: OIDCは、OAuth 2.0をベースにしており、ユーザーが外部のIdP(例えば、Google、GitHub、Oktaなど)を使用して認証できるようにします。
トークンベースの認証: 認証が成功すると、IdPはIDトークン(JWT形式)を発行します。このトークンには、ユーザー情報や認証情報が含まれています。
別プロバイダー(別サービス)からAWSにアクセスする際にそのプロバイダーに対しIAM権限を付与できるといったところでしょうか。
AWSコンソールにて設定
上記記事を参考に作成しました。
IDプロバイダの作成
AWSコンソール->IAM->サイドメニュー/プロバイダ->プロバイダの作成より以下のように設定しました。
- プロバイダの設定
- プロバイダのタイプ:
OpenID Connect
- プロバイダの URL:
https://token.actions.githubusercontent.com
- 対象者:
sts.amazonaws.com
- プロバイダのタイプ:
ロールの作成
AWSコンソール->IAM->サイドメニュー/ロール->ロールの作成より遷移
- 信頼されたエンティティタイプ:
カスタム信頼ポリシー
- カスタム信頼ポリシーは以下を参考に設定
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{AWSアカウントID}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:{GitHubのユーザー名}/{リポジトリ名}:ref:refs/heads/{ブランチ名}"
}
}
}
]
}
- 許可を追加
- 以下を追加
AmazonEC2ContainerRegistryPowerUser
AmazonS3FullAccess
上記を設定しロールを作成
GithubActions作成
secrets
に関して
GithubActions内の- GithubActionsにて外部に晒したくない情報は秘匿情報として管理できます。
- GitHubのリポジトリ->settings->サイドメニュー->Secrets&Variable->Actionsより以下のような画面へ遷移できます。
- 追加を行う際は
New Repositorysecret
より行います。
AWSへの認証
GithubActions内のAWSの認証はとてもシンプルです。
uses
にてaws-actions/configure-aws-credentials@v1
を指定し、role-to-assume
にて作成したロールのARNを指定してあげるだけです。
~
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-1
role-to-assume: 'arn:aws:iam::{AWSアカウントID}:role/{作成したロール名}'
~
また注意するポイントとしてpermittions
にて以下のように設定をしないとエラーになるため、気をつける必要があります
~
permissions:
id-token: write
contents: read
~
sync
コマンド実行しアップロード
S3へビルドしたReactプロジェクトを以下はReactプロジェクト用のものです。working-directory
等はよしなに置き換えてください
name: Deploy React App
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-1
role-to-assume: 'arn:aws:iam::{AWSアカウントID}:role/GithubActionsRoleforASS'
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16.15.1'
- name: Install modules
run: npm ci
working-directory: ./frontend/app
- name: Build application
run: npm run build
working-directory: ./frontend/app
- name: Deploy to S3
run: aws s3 sync --delete ./build/ s3://${{ secrets.BUCKET_ID }} --region ap-northeast-1
working-directory: ./frontend/app
ECRリポジトリへコンテナイメージのpush
上記同様working-directory
等はよしなに置き換えてください
name: Push ECR for Rails and Nginx
on:
push:
branches:
- main
jobs:
PushRailstoECR:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-1
role-to-assume: 'arn:aws:iam::{AWSアカウントID}:role/GithubActionsRoleforASS'
- name: Login ECR
run: |
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_ENDPOINT }}
- name: Image Build & Push to Rails ECR
env:
RAILS_REPOSITORY: "{Rails用ECRリポジトリ名}"
IMAGE_TAG: latest
run: |
docker build --no-cache -f ./docker/staging/Dockerfile --platform linux/amd64 -t ${{ env.RAILS_REPOSITORY }} .
docker tag ${{ env.RAILS_REPOSITORY }}:latest 730335441282.dkr.ecr.ap-northeast-1.amazonaws.com/${{ env.RAILS_REPOSITORY }}:${{ env.IMAGE_TAG }}
docker push {AWSアカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/${{ env.RAILS_REPOSITORY }}:${{ env.IMAGE_TAG }}
working-directory: ./backend
- name: Image Build & Push to Nginx ECR
env:
NGINX_REPOSITORY: "{Nginx用ECRリポジトリ名}"
IMAGE_TAG: latest
run: |
docker build --no-cache --platform linux/amd64 -t ${{ env.NGINX_REPOSITORY }} .
docker tag ${{ env.NGINX_REPOSITORY }}:latest 730335441282.dkr.ecr.ap-northeast-1.amazonaws.com/${{ env.NGINX_REPOSITORY }}:${{ env.IMAGE_TAG }}
docker push {AWSアカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/${{ env.NGINX_REPOSITORY }}:${{ env.IMAGE_TAG }}
working-directory: ./nginx
上記ではRails用のイメージとリバースプロキシ用のNginxのイメージをまとめて、ビルド・タグつけ・pushを行なっています。
終わりに
OIDCと聞くとすごく複雑なイメージがあり少し敬遠していましたが使ってみるとシンプルでとても使いやすいと実感できました。別プロバイダとAWS間でやりとりを行う際は積極的に使っていきたいと思います!
Discussion