lambda-cicd-workshop

フェーズ7: OIDC – GitHubとAWSの信頼関係を構築する

フェーズ5・6では、人間がブラウザでログインしてAWSを操作しました。このフェーズでは、GitHub Actionsが同じようにAWSを操作するための認証を設定します。

OIDCとは

GitHub ActionsからAWSを操作するには、AWSの認証情報が必要です。アクセスキーをGitHubに保存する方法もありますが、永続的な秘密情報の管理はリスクになります。

OIDC(OpenID Connect)を使うと、GitHubとAWSの間にあらかじめ信頼関係を結んでおくことで、ワークフロー実行時にAWSから一時的な認証情報を取得して処理します。

OIDCのフロー

実行時の認証フローは以下のとおりです。

  1. GitHub Actionsワークフローが、GitHubのOIDCプロバイダにJWTトークンを要求する
  2. AWS STS が AssumeRoleWithWebIdentity でJWTトークンを検証し、一時的な認証情報を返す
  3. GitHub Actionsが、取得した認証情報でIAMロールとしてLambda関数を操作する

aws loginとのアナロジー

aws login を思い出してください。

  1. コマンドを実行するとブラウザが開く
  2. マネジメントコンソールにサインインする
  3. AWSが「この人は信頼できる」と判断し、一時的な認証情報を渡す
  4. 以降、CLIでAWSを操作できる

OIDCも構造は同じです。

  1. GitHub Actionsがワークフローを実行する
  2. GitHubが「自分はこのリポジトリである」という証明書(トークン)を発行する
  3. AWSが「このリポジトリは信頼できる」と判断し、一時的な認証情報を渡す
  4. 以降、GitHub Actions上でAWSを操作できる

違いは「誰が認証するか」だけです。

  認証する主体 信頼の根拠 認証情報
aws login 人間 ブラウザでのサインイン 一時的
OIDC GitHub Actions リポジトリの証明書(トークン) 一時的

CloudFormationでOIDCとIAMロールを作成する

このフェーズで作成するリソースは以下の2つです。

これらをCloudFormationテンプレート(oidc.yml)にまとめています。

テンプレートの内容

AWSTemplateFormatVersion: "2010-09-09"
Description: GitHub Actions OIDC provider and IAM role for deploy

Parameters:
  GitHubOrg:
    Type: String
    Description: GitHub organization or user name
  GitHubRepo:
    Type: String
    Description: GitHub repository name

Resources:
  GitHubOIDCProvider:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ClientIdList:
        - sts.amazonaws.com

  GitHubActionsRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: github-actions-deploy
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: !GetAtt GitHubOIDCProvider.Arn
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: sts.amazonaws.com
              StringLike:
                token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${GitHubRepo}:ref:refs/heads/*
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/PowerUserAccess

Outputs:
  RoleArn:
    Description: IAM Role ARN for GitHub Actions
    Value: !GetAtt GitHubActionsRole.Arn

権限について

このワークショップでは利便性を優先して PowerUserAccess を使っています。実際の環境では、必要最小限の権限だけを付与する 最小権限の原則 に従ってください。

注意

以前はOIDCプロバイダに ThumbprintList の指定が必要でしたが、現在は不要です。設定されていても無視されます。

GitHubActionsRoleAssumeRolePolicyDocument が信頼ポリシーです。Conditionsub で、指定したリポジトリからのリクエストだけを許可しています。

同じURLのOIDCプロバイダは、1つのAWSアカウントに1つしか作成できません。すでに別のスタックやツールで token.actions.githubusercontent.com のOIDCプロバイダを作成済みの場合、このテンプレートのデプロイは失敗します。その場合は、既存のプロバイダをそのまま利用し、テンプレートから GitHubOIDCProvider リソースを削除して、IAMロールの Federated に既存プロバイダのARNを直接指定してください。

デプロイ

AWSコンソールからCloudFormationスタックを作成します。

AWSコンソールで CloudFormation → スタックの作成 → 既存のテンプレートを選択 → テンプレートファイルのアップロード を選択して、oidc.yml をアップロードしてください。

パラメータの入力画面で、以下を自分のリポジトリに合わせて設定します。

スタック名は github-actions-oidc などにしてください。

IAMリソースを作成するため、確認画面で「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します」にチェックを入れてください。

デプロイが完了したら、CloudFormationの「出力」タブで RoleArn の値を確認してください。次のフェーズで使います。

AWS CLIからのデプロイ

AWS CLI を使って、以下のようにしてデプロイすることもできます。

aws cloudformation deploy \
  --template-file oidc.yml \
  --stack-name github-actions-oidc \
  --parameter-overrides \
    GitHubOrg=YOUR_GITHUB_ORG \
    GitHubRepo=YOUR_REPO_NAME \
  --capabilities CAPABILITY_NAMED_IAM \
  --profile cli-profile

備考:OIDCの対応関係

GitHub Actions が AWS リソースに OIDC を使ってアクセスする場合、OIDC の用語と GitHub Actions/AWS の役割を対応付けると以下のようになります。

OIDC 用語 役割 GitHub Actions / AWS での該当
Identity Provider (IdP) アイデンティティを証明する機関 GitHub (正確には GitHub のトークン発行サーバー)
Relying Party (RP) IdP を信頼して認証を受け入れる側 AWS (具体的には AWS STS)
Subject (sub) 認証の対象となる実体 GitHub Actions のワークフロー実行単位 (リポジトリ、ブランチ、環境など)
Token (JWT) IdP が発行する身分証明書 GitHub Actions が生成する OIDC ID トークン

このフェーズのまとめ

参考リンク

次のステップ

GitHubとAWSの信頼関係が構築できました。次のフェーズでは、この信頼関係を使ってGitHub Actionsからデプロイを自動化します。

フェーズ8: CD に進みましょう。