GitHub ActionsにAWSクレデンシャルを直接設定したくないのでIAMロールを利用したい
こんにちは!コンサル部のinomaso(@inomasosan)です。
前回と前々回でGitHub ActionsからECSのCI/CDやIAMポリシーの最小権限作成を試してみました。
今回はGitHub ActionsでAWSの一時的なクレデンシャル(アクセスキーID、シークレットアクセスキー)を利用したいので、IAMユーザーの代わりにOIDCプロバイダとIAMロールを設定していきます。
IAMユーザーのクレデンシャルだとダメなの?
IAMユーザーで発行したクレデンシャルは永続的に利用可能です。
GitHubではAWSのクレデンシャルをSecrets
により秘匿化できますが、AWS外のサービスに永続的なクレデンシャルを設定するのは、セキュリティや運用で課題になることが多いです。
AWSの内外問わず、AWSクレデンシャルの直接的な設定を可能な限り避けるのが基本的な考え方です。そのため、IAMロールの一時的なクレデンシャルを利用できないかを最初に検討する必要があります。
やってみた
OIDCプロバイダやIAMロールの作成は、サンプルのCloudFormationテンプレートが用意されていますが、今回はそちらを参考にAWSマネジメントコンソールで作成していきます。
OIDCプロバイダ追加
IAMコンソールのIDプロバイダ
から、GitHubが提供するOIDCプロバイダを追加していきます。
- プロバイダのタイプ: OpenID Connect
- プロバイダの URL: https://token.actions.githubusercontent.com
- 対象者: sts.amazonaws.com
IAMロール作成
IAMコンソールのロール
から、GitHub ActionsからECSとECRへのCI/CDを最小権限で実行したいのIAMポリシーをアタッチしたIAMロールを作成します。
信頼されたエンティティはIAMロール作成後に編集するので、いったんEC2等を選択してください。
IAMロールを一度作成しましたら信頼関係の編集
からポリシードキュメントを編集します。
<>
で囲った値は、ご自身の環境毎の値に置き換えてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<AWSアカウントID>:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:<GitHubユーザー名>/<GitHubリポジトリ名>:*" } } } ] }
GitHub Actionsワークフロー修正
[初心者向け] GitHub ActionsからECS FargateにCI/CDしてみたで作成したワークフローを、サンプルを元に修正していきます。
以下がワークフローの全体で、修正が必要な箇所をハイライトしました。
# This workflow will build and push a new container image to Amazon ECR, # and then will deploy a new task definition to Amazon ECS, when there is a push to the main branch. # # To use this workflow, you will need to complete the following set-up steps: # # 1. Create an ECR repository to store your images. # For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`. # Replace the value of the `ECR_REPOSITORY` environment variable in the workflow below with your repository's name. # Replace the value of the `AWS_REGION` environment variable in the workflow below with your repository's region. # # 2. Create an ECS task definition, an ECS cluster, and an ECS service. # For example, follow the Getting Started guide on the ECS console: # https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun # Replace the value of the `ECS_SERVICE` environment variable in the workflow below with the name you set for the Amazon ECS service. # Replace the value of the `ECS_CLUSTER` environment variable in the workflow below with the name you set for the cluster. # # 3. Store your ECS task definition as a JSON file in your repository. # The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`. # Replace the value of the `ECS_TASK_DEFINITION` environment variable in the workflow below with the path to the JSON file. # Replace the value of the `CONTAINER_NAME` environment variable in the workflow below with the name of the container # in the `containerDefinitions` section of the task definition. # # 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. # See the documentation for each action used below for the recommended IAM policies for this IAM user, # and best practices on handling the access key credentials. name: Deploy to Amazon ECS on: push: branches: - main env: AWS_REGION: ap-northeast-1 # set this to your preferred AWS region, e.g. us-west-1 ECR_REPOSITORY: githubactions-httpd # set this to your Amazon ECR repository name ECS_SERVICE: httpd-service # set this to your Amazon ECS service name ECS_CLUSTER: httpd-cluster # set this to your Amazon ECS cluster name ECS_TASK_DEFINITION: task-definition.json # set this to the path to your Amazon ECS task definition # file, e.g. .aws/task-definition.json CONTAINER_NAME: httpd-container # set this to the name of the container in the # containerDefinitions section of your task definition AWS_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:<GitHub Actions用のIAMロール名>/ # GitHub Actions用に作成したIAMロールのARN jobs: deploy: name: Deploy runs-on: ubuntu-latest environment: production # These permissions are needed to interact with GitHub's OIDC Token endpoint. permissions: id-token: write contents: read steps: - name: Checkout uses: actions/checkout@v2 - name: Configure AWS credentials from IAM Role uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: ${{ env.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build, tag, and push image to Amazon ECR id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | # Build a docker container and # push it to ECR so that it can # be deployed to ECS. docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" - name: Fill in the new image ID in the Amazon ECS task definition id: task-def uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ env.ECS_TASK_DEFINITION }} container-name: ${{ env.CONTAINER_NAME }} image: ${{ steps.build-image.outputs.image }} - name: Deploy Amazon ECS task definition uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: ${{ steps.task-def.outputs.task-definition }} service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} wait-for-service-stability: true
43行目
env
にGitHub Actions用に作成したIAMロールのARNを追加します。
<>
で囲った値は、ご自身の環境毎の値に置き換えてください。
50~53行目
permissions
でGitHub Actionsの実行ごとに発行されるGitHubのTokenの権限を設定します。
id-token: write
は、GitHubのOIDCプロバイダが発行されるトークンを利用するために必要となります。
またpermissions
で権限を変更すると、指定しなかった権限はnone
になってしまいます。
そのためcontents
をデフォルトのread
権限にするためには明示的な指定が必要です。
58~62行目
aws-access-key-id
やaws-secret-access-key
の指定は不要です。
role-to-assume
のみを指定すれば、OIDCプロバイダのトークンで認証を開始してくれます。
認証の詳細なフローはGetting started with OIDCをご参照ください。
GitHub Secrets設定
IAMユーザ使用時にSecrets
へ設定した、AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
は不要なため削除しましょう。
代わりにGitHub Actions用のIAMロールのARN指定にAWSアカウントIDが必要なため、AWS_ACCOUNT_ID
を追加します。
AWSアカウントIDはワークフローに直書きできますが、セキュリティの観点からSecretsで秘匿化するのをオススメいたします。
ワークフロー実行
変更したファイルを、GitHubリポジトリにプッシュします。
git add . git commit -m 'AWS credential of IAM Role' git push
GitHub Actionsワークフローによるデプロイが正常に完了したことを確認できました。
あわせて読みたい記事
まとめ
AWSの一時的なクレデンシャルの使用は設定が難しいかと思ったのですが、Github Actionsで必要な知識を順を追って学習していくことで、すんなり理解することができました。
ここ数日の検証でGitHub ActionsによるCI/CDが楽しくなってきたので、学習に対するモチベーションが上がったと思います!
この記事が、どなたかのお役に立てば幸いです。それでは!