GitHub ActionsでOIDCを介したAWS ECRイメージの更新
現代のソフトウェア開発サイクルでは、CI/CD(Continuous Integration/Continuous Deployment)が重要な役割を果たしています。このプロセスの重要な側面の1つは、Amazon Elastic Container Registry(ECR)などのクラウドベースのリポジトリにDockerイメージをデプロイすることです。この記事では、GitHub ActionsとOpenID Connect(OIDC)プロトコルを使用してECRイメージをプッシュするプロセスについて詳しく説明します。
OIDCとは
GitHub Actionsのワークフローは、AWS、Google Cloud Platform(GCP)、またはAzureなどのクラウドプロバイダーにアクセスし、ソフトウェアをデプロイしたりクラウドサービスを利用したりするために使用されることがあります。これらの異なるプラットフォーム間の安全な通信を容易にするために、OpenID Connect(OIDC)が使用されます。
OIDCは、認証サーバーによって実行された認証に基づいてエンドユーザーのアイデンティティを検証するアイデンティティ層です。これにより、ワークフローの実行時にクレデンシャルを発行し、クラウドへのデプロイ時の認証に使用することが可能になります。これらの資格情報は一時的なものであり、永続的なアクセスキーを使用する場合と比較して、漏洩した場合の悪用のリスクを減らします。
2022年9月時点で、OIDCをサポートしているクラウドプロバイダーは次のとおりです。
- AWS
- Azure
- GCP
- HashiCorp Vault
ソースコード
ディレクトリ構造
プロジェクトのディレクトリ構造は次のように構成されています。
.
├── .github/workflows/deploy-ecr.yml
├── Dockerfile
└── terraform
├── variables.tf
├── iam.tf
└── ecr.tf
Terraform
次のコードは、OIDCプロバイダー、ロール、およびECRリポジトリを定義しています。
variable "env" {
default = "dev"
}
variable "github_provider" {
default = "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
}
variable "aws_account_id" {
default = "123456789012"
}
variable "github_org" {
default = "mycompany-inc"
}
variable "github_repo" {
default = "my-repo"
}
resource "aws_iam_openid_connect_provider" "main" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}
resource "aws_iam_role" "github_actions" {
name = "${var.env}-github-actions"
assume_role_policy = jsonencode(
{
"Version" = "2012-10-17"
"Statement" = [
{
"Principal" : {
"Federated" : "arn:aws:iam::${var.aws_account_id}:oidc-provider/token.actions.githubusercontent.com"
},
"Action" : [
"sts:AssumeRoleWithWebIdentity",
],
"Effect" = "Allow",
"Condition" : {
"StringLike" : {
"token.actions.githubusercontent.com:aud" : "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub" : "repo:${var.github_org}/${var.github_repo}:*"
}
},
}
]
}
)
}
resource "aws_iam_policy" "github_actions_policy" {
name = "${var.env}-github-actions-policy"
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "ImageUploader",
"Action" : [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:GetAuthorizationToken",
],
"Effect" = "Allow",
"Resource" = "*"
}
],
})
}
resource "aws_iam_role_policy_attachment" "github_actions_ecr_policy_attachment" {
policy_arn = aws_iam_policy.github_actions_policy.arn
role = aws_iam_role.github_actions.id
}
resource "aws_iam_role_policy_attachment" "github_actions_ecs_full_access" {
policy_arn = "arn:aws:iam::aws:policy/AmazonECS_FullAccess"
role = aws_iam_role.github_actions.id
}
resource "aws_ecr_repository" "main" {
name = "my-ecr-repo"
}
Github Actions
次のシークレットをGitHubの「Settings」>「New repository secret」から登録します。
AWS_GA_ROLE_ARN
(Terraformで定義されたaws_iam_role.github_actions
のARN)AWS_ECR_REPO_NAME
(Terraformで定義されたECRリポジトリ名)
そして、リポジトリ内の.github/workflows/deploy.yml
に次のYMLファイルを記述します。
name: Deploy ECR Image
on:
push:
branches:
- develop
permissions:
id-token: write
contents: read
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-1
role-to-assume: ${{ secrets.AWS_GA_ROLE_ARN }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push Docker image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY . --no-cache
docker push $ECR_REGISTRY/$ECR_REPOSITORY
参考