GitHub Actions から安全に AWS の IAM ロールを引き受けるベストプラクティス
GitHub Actions にて CI/CD を構築しているとき、AWS リソースにアクセスしたくなるときがありますよね?そのような時には、OpenID Connect (OIDC) を利用したフローにて IAM ロールを引き受けることが推奨されます。
本記事では、IAM ロール引き受けまでのフローと具体的な手順をご紹介いたします!
ロール引き受け方法
まず、IAM ロールを引き受ける方法を考える中で、すべての選択肢を把握しておく必要があります。IAM ロールの引き受け方法は AWS ドキュメント にまとめられています。
この中で、AWS 外部で IAM ロールを引き受ける際には OpenID Connect (OIDC) が最も堅実な選択肢です。
OIDCを使用する利点
OpenID Connect (OIDC) を使用して GitHub Actions から AWS IAM ロールを引き受けることには、いくつかの重要な利点があります。
- シークレットの静的保存が不要: 長期的な AWS アクセスキーやシークレットを GitHub シークレットに保存する必要がありません。これにより、認証情報漏洩のリスクが大幅に軽減されます。
- 認証情報のローテーションが自動化: OIDC を使用すると、一時的な認証情報が自動的に生成されるため、手動での認証情報の更新やローテーションが不要になります。
- きめ細かいアクセス制御: IAM 信頼ポリシーを使用して、特定のリポジトリ、ブランチ、タグなどに基づいてアクセスを制限できるため、最小権限の原則に従ったセキュリティ設計が可能です。
- 監査性の向上: すべてのアクションは特定の GitHub ワークフローに関連付けられており、AWS CloudTrail でのロギングと監査が容易になります。
- 管理の簡素化: 複数のサービスアカウントやアクセスキーを管理する代わりに、信頼関係に基づく連携を設定するだけで済みます。
これらの利点により、OIDC は GitHub Actions と AWS の統合における現在のベストプラクティスとなっています。
今回も OIDC によるロール引き受けを使用します。
ロール引き受けまでのフロー
今回ご紹介する GitHub Actions でのロール引き受け手順は、AWS IAM の Web Identity の一般的な流れと同じです。
sequenceDiagram participant Workflow as GitHub Workflow participant OIDCProvider as GitHub OIDC Provider participant AWSSTS as AWS STS participant AWSService as AWS Service Note over Workflow: 実行環境からIDトークンを要求 Workflow->>OIDCProvider: リポジトリ情報などを含めてリクエスト OIDCProvider-->>Workflow: JWT形式のIDトークンを発行 Workflow->>AWSSTS: AssumeRoleWithWebIdentity(IDトークンを添付) AWSSTS->>OIDCProvider: JWKs取得 AWSSTS->>AWSSTS: JWT署名・iss・aud・exp・sub等を検証 AWSSTS->>AWSSTS: IAMロールの信頼ポリシーと照合 AWSSTS-->>Workflow: 一時認証情報を返却 Workflow->>AWSService: 一時認証情報でアクセス AWSService-->>Workflow: レスポンス
手順
- Identity Provider の作成
- IAM ロールの作成
- GitHub Actions の設定ファイルの作成
Identity Provider の作成
IAM > Identity providers から新しい Identity providers を作成します。入力する値は固定値です。
- Provider URL:
https://token.actions.githubusercontent.com - Audience:
sts.amazonaws.com
IAM ロールの作成
マネジメントコンソールから IAM ロールを作成する場合、以下のような設定にします。
- Identity provider: 作成した IdP を選択
IdP を選択すると、クレーム情報の入力ができます。sub の部分はユーザー名・リポジトリ名・ブランチ名に分かれて入力補助が出ます。
- Audience:
sts.amazonaws.comを選択 - GitHub organization: 組織名またはユーザー名
- GitHub repository: リポジトリ名 (任意)
- GitHub branch: ブランチ名 (任意)
信頼ポリシーは以下のようになります。IaC で作成するときなどの参考にしてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::{アカウントID}:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" }, "StringLike": { "token.actions.githubusercontent.com:sub": "repo:{ユーザー・組織名}/{リポジトリ名}:*" } } } ] }
GitHub Workflows の作成
aws-actions/configure-aws-credentials を使用することで、自動でクレデンシャルを取得しロールを引き受けることができます。
なお、今回は Rust でテストコードを用意しているため、Rust のための GitHub Actions が例に含まれています。
name: Fetch SSM Parameter on: workflow_dispatch: env: AWS_REGION: "ap-northeast-1" permissions: id-token: write contents: read jobs: test: name: Unit Test runs-on: ubuntu-latest steps: - name: Clone Repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: configure aws credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.IAM_ROLE_ARN }} role-session-name: samplerolesession aws-region: ${{ env.AWS_REGION }} - name: Setup Rust Toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Run run: cargo run
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; let client = aws_sdk_ssm::Client::new(&config); let value = client .get_parameter() .name("/message") .send() .await? .parameter .and_then(|p| p.value) .unwrap_or_default(); println!("{}", value); Ok(()) }