エキサイト株式会社の@mthiroshiです。
GitHub Actions から AWS ECS にコンテナアプリケーションをデプロイする際に、OIDC 認証を使用して AWS にアクセスする方法を試してみました。その内容について紹介します。
GitHub 公式ドキュメントは下記です。 docs.github.com
- OpenID Connect(OIDC)とは
- AWS IAM の ID プロバイダーに GtiHub OIDC プロバイダーを追加
- GitHub Actions 用の IAM ロールを作成
- GitHub Actions の設定
- 最後に
- 採用情報
- 参考記事
OpenID Connect(OIDC)とは
OpenID Connect(OIDC)は、OAuth 2.0 フレームワーク仕様に基づいた認証プロトコルです。 OIDC を利用することで、アプリケーションはユーザーを検証し、必要なユーザー情報を取得できます。
GitHub Actions から AWS ECS へデプロイする場合、AWS へのアクセスには認証が必要となります。 認証方法の一つとして、IAM ユーザーのアクセスキーとシークレットキーを用いる方法がありましたが、この方法はキーのセキュアな管理が必要であり、運用上の課題となっていました。
それに対して OIDC を用いる場合では、有効期間の短いクレデンシャルを AWS から直接要求するようにワークフローを構成できます。 OIDC では、アクセストークンと呼ばれる有効期限付きのトークンを発行するため、アクセスキーやシークレットキーのように永続的に管理する必要がなく、セキュリティリスクを低減することができます。
AWS IAM の ID プロバイダーに GtiHub OIDC プロバイダーを追加
GitHub の OIDC プロバイダー を AWS IAM の ID プロバイダに追加します。これによって、GitHub と AWS アカウント間の信頼を確立します。
Terraform コードを紹介します。
data "tls_certificate" "github_actions_deploy" { url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration" } resource "aws_iam_openid_connect_provider" "github_actions_deploy" { url = "https://token.actions.githubusercontent.com" client_id_list = ["sts.amazonaws.com"] thumbprint_list = [data.tls_certificate.github_actions_deploy.certificates[0].sha1_fingerprint] }
aws_iam_openid_connect_provider
リソースによって、IAM OIDC ID プロバイダーを作成できます。
下記ページを参考にして、パラメータの値を当てはめています。 docs.github.com
For the provider URL: Use https://token.actions.githubusercontent.com
For the "Audience": Use sts.amazonaws.com if you are using the official action.
thumbprint_list
には、 OIDC ID プロバイダーのサーバー証明書のサーバー証明書のサムプリントが求められるので、 tls_certificate
data リソースによって取得し、設定します。
GitHub Actions 用の IAM ロールを作成
GitHub Actions から AWS にアクセスするための IAM ロールを作成します。 IAM ロールを作成し、下記の3種類の IAM ポリシーをアタッチします。
- OIDC 認証用の信頼ポリシー
- ECS デプロイ用の許可ポリシー(アプリケーション共通)
- ECS デプロイ用の許可ポリシー(アプリケーション個別)
まず、 IAM ロール作成と、OIDC 認証の 信頼 ポリシー、ECS デプロイ用の許可ポリシー(アプリケーション共通)のアタッチについて、Terraform コードを示します。
data "aws_iam_policy_document" "github_actions_deploy_assume_policy" { statement { principals { type = "Federated" identifiers = [ aws_iam_openid_connect_provider.github_actions_deploy.arn ] } actions = [ "sts:AssumeRoleWithWebIdentity" ] condition { test = "StringLike" variable = "token.actions.githubusercontent.com:sub" values = ["repo:<GitHubオーガニゼーション>/<GitHubリポジトリ名>:*"] } } } resource "aws_iam_role" "github_actions_deploy" { name = "github-actions-deploy" description = "IAM Role for GitHub Actions Deploy ECS" assume_role_policy = data.aws_iam_policy_document.github_actions_deploy_assume_policy.json } data "aws_caller_identity" "self" {} data "aws_iam_policy_document" "github_actions_deploy_policy" { statement { sid = "GetAuthorizationToken" actions = [ "ecr:GetAuthorizationToken" ] resources = ["*"] } statement { sid = "RegisterTaskDefinition" actions = [ "ecs:RegisterTaskDefinition" ] resources = ["*"] } statement { sid = "PassRole" actions = [ "iam:PassRole" ] resources = [ "arn:aws:iam::${data.aws_caller_identity.self.account_id}:role/ecsTaskExecutionRole" ] condition { test = "StringLike" variable = "iam:PassedToService" values = ["ecs-tasks.amazonaws.com"] } } } resource "aws_iam_policy" "github_actions_deploy" { name = "github-actions-deploy" policy = data.aws_iam_policy_document.github_actions_deploy_policy.json } resource "aws_iam_role_policy_attachment" "role_policy_attachment" { role = aws_iam_role.github_actions_deploy.name policy_arn = aws_iam_policy.github_actions_deploy.arn }
data "aws_iam_policy_document" "github_actions_deploy_assume_policy"
では、先ほどの OIDC IDプロバイダーを指定し、AssumeRoleWithWebIdentity
アクションによって、一時的な認証情報を取得できるように信頼ポリシーを作成しています。
認証の条件に、 GitHub リポジトリの指定もできます。
そして、data "aws_iam_policy_document" "github_actions_deploy_policy"
では、デプロイ用の許可ポリシー(アプリケーション共通)を設定しています。ECRのログイン、ECSのタスク定義登録などのポリシーです。
タスク実行ロール( ecsTaskExecutionRole
) に iam:PassRole
をしています。タスク実行の際に、OIDC 認証のポリシーが必要となるためです。
次に、ECS デプロイ用の許可ポリシー(アプリケーション個別)の設定です。
data "aws_iam_policy_document" "github_actions_deploy" { statement { sid = "PushImageOnly" actions = [ "ecr:BatchCheckLayerAvailability", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", "ecr:PutImage" ] resources = [ "arn:aws:ecr:ap-northeast-1:<AWSアカウントID>:repository/<リポジトリ名>", ] } statement { sid = "UpdateService" actions = [ "ecs:UpdateServicePrimaryTaskSet", "ecs:DescribeServices", "ecs:UpdateService" ] resources = [ "arn:aws:ecs:ap-northeast-1:<AWSアカウントID>:service/<サービス名>" ] } statement { sid = "PassRole" actions = [ "iam:PassRole" ] resources = [ "arn:aws:iam::<AWSアカウントID>:role/<タスクロール>" ] } } resource "aws_iam_policy" "github_actions_deploy" { name = "github-actions-deploy-policy" policy = data.aws_iam_policy_document.github_actions_deploy.json } resource "aws_iam_role_policy_attachment" "role_policy_attachment" { role = "arn:aws:iam::<AWSアカウントID>:role/<タスクロール>", policy_arn = aws_iam_policy.github_actions_deploy.arn }
ecr:PutImage
や ecs:UpdateSerivice
などのアクションでは、それを実行できるアプリケーションを制限しようと考えました。そのように設定するためには、ECS サービスのarnを動的に参照する必要があったため、Terraformを分ける運用としました。
ECS タスクロールにも OIDC 認証を渡せるように iam:PassRole
を設定します。
GitHub Actions の設定
ECS にコンテナをデプロイする GitHub Actions の yaml のサンプルコードを示します。
簡単に、チェックアウトから、ECRログイン、ビルド、タスク定義のデプロイまでを示しています。
name: Deploy ECS on: workflow_dispatch: permissions: contents: read id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::<AWSアカウントID>:role/github-actions-deploy aws-region: ap-northeast-1 - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 # ビルド 省略 - name: Deploy Amazon ECS task definition uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: task-definition.json cluster: "sample_ecs_cluster" service: "sample_ecs_service" wait-for-service-stability: true
今回の趣旨のポイントを説明します。
まず、 permissions
に id-token: write
が必要になります。これによって、GitHubの OIDC プロバイダーから JWT を要求できます。
そして、aws-actions/configure-aws-credentials@v4
action の role-to-assume
に作成した IAM ロールの ARN を指定します。これで AWS へアクセスが可能になり、以降のECR ログイン等の処理が実行できます。
最後に
GitHub Actions から OIDC 認証によって AWS へアクセスする方法について、まとめてみました。 IAM ロール、ポリシー周りは、理解が浅くてハマった部分でした。ここは改めて整理しておきたいと思います。 参考になれば幸いです。
採用情報
エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。
募集職種一覧はこちらになります!(カジュアル面談もぜひ!) www.wantedly.com
参考記事
アマゾン ウェブ サービスでの OpenID Connect の構成 - GitHub Enterprise Cloud Docs