エムオーテックス株式会社が運営するテックブログです。

マルチアカウント環境における IAM OIDC ID プロバイダーの設計パターン

マルチアカウント環境における IAM OIDC ID プロバイダーの設計パターン

はじめに

こんにちは、アプリケーションチームの小沼です。

LANSCOPE エンドポイントマネージャークラウド版(以下、クラウド版)では、ソースコードの管理をAWS CodeCommit からGitHub への変更を検討しています。

クラウド版ではAWS をマルチアカウント構成で利用しています。AWS とGithubを連携する際に以下の悩みに直面しました。

  • IAM OIDC ID プロバイダーが必要になることはわかったが、これは一つ用意すればいいのか?それともアカウントごとに用意すればいいのか?

本記事では、マルチアカウント環境におけるIAM OIDC ID プロバイダーを使った GitHub と AWS連携の設計パターンを共有します。

IAM OIDC IDプロバイダーとは

IAM OIDC ID プロバイダーは OpenID Connect (OIDC) 標準 (例: Google または Salesforce) をサポートする ID プロバイダー (IdP) サービスを表す IAM のエンティティです。OIDC 互換 IdP と AWS アカウント の間で信頼性を確立するときに IAM OIDC ID プロバイダーを使用します。

docs.aws.amazon.com

OIDC(OpenID Connect)を使用すると、GitHub Actionsが発行する一時的なトークンを使い、IAM Role を引き受ける仕組みです。
GitHub Actions が引き受けるIAM Role には、GitHub Actions が実行できるポリシーを定義します。 ポリシーを適切に管理することで、開発者は安心してGitHub Actions のワークフローを作成できます。

開発アカウントごとにIAM OIDC ID プロバイダーを用意する場合

各開発アカウント上にAWS IAM OIDC ID プロバイダーを設定

GitHub Actions のワークフローは以下の様になります

name: s3 ls test

on:
  workflow_dispatch:

permissions:
  id-token: write   
  contents: read

jobs:
  s3-list:
    runs-on: test-runner

    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v5
        with:
          role-to-assume: arn:aws:iam::${{ 開発環境のAWS_ACCOUNT_ID }}:role/GitHubActions-Role
          aws-region: ap-northeast-1
      
      - name: List S3 buckets
        run: aws s3 ls

各開発アカウントでIAM OIDC ID プロバイダーを用意し、GitHub Actions で必要になる許可ポリシーを用意します。

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

  GitHubTestRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub GitHubActions-Role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Ref GitHubOIDCProvider
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: sts.amazonaws.com
              StringLike:
                token.actions.githubusercontent.com:sub: repo:<your-org>/<your-repo>:ref:refs/heads/<branch-name>
      ManagedPolicyArns:
        - !Ref GitHubTestPolicy
      Path: /

  GitHubTestPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub GitHubActions-Policy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - s3:ListAllMyBuckets
              - s3:GetBucketLocation
            Resource: "*"
          - Effect: Allow
            Action:
              - s3:ListBucket
              - s3:GetObject
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::*
              - !Sub arn:${AWS::Partition}:s3:::*/*

共通のIAM OIDC ID プロバイダーを用意する場合

共通アカウントにAWS IAM OIDC ID プロバイダーを設定

GitHub Actions のワークフローは以下になります

name: s3 ls test

on:
  workflow_dispatch:

permissions:
  id-token: write  
  contents: read

jobs:
  s3-list:
    runs-on: test-runner

    steps:
      # ステップ1: 共通アカウントのハブロールを取得
      - name: Configure AWS credentials (Hub Role)
        uses: aws-actions/configure-aws-credentials@v5
        with:
          role-to-assume: arn:aws:iam::${{ 共通アカウントのAWS_ACCOUNT_ID }}:role/GitHubActions-Hub-Role
          aws-region: ap-northeast-1
      
      # ステップ2: 開発アカウントのターゲットロールにAssumeRole
      - name: Configure AWS credentials (Target Role)
        uses: aws-actions/configure-aws-credentials@v5
        with:
          role-to-assume: arn:aws:iam::${{ 開発アカウントのAWS_ACCOUNT_ID }}:role/GitHubActions-Target-Role
          aws-region: ap-northeast-1
          role-chaining: true
          role-skip-session-tagging: true
      
      - name: List S3 buckets
        run: aws s3 ls

共通アカウントに IAM OIDC ID プロバイダーとAssume Role するためのポリシーを用意します。

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

  GitHubActionsHubRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: GitHubActions-Hub-Role
      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: repo:<your-org>/<your-repo>:ref:refs/heads/<branch-name>
      ManagedPolicyArns:
        - !Ref HubRolePolicy
      Path: /

  HubRolePolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: GitHubActions-Hub-Policy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - sts:AssumeRole
            Resource:
              - !Sub arn:aws:iam::${ 開発アカウントのAWS_ACCOUNT_ID }:role/GitHubActions-Target-Role

開発アカウントにGitHub Actions で必要になる許可ポリシーを用意します。

  GitHubActionsDevRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: GitHubActions-Target-Role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${ 共通アカウントのAWS_ACCOUNT_ID }:role/GitHubActions-Hub-Role
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - !Ref TargetRolePolicy
      Path: /

  TargetRolePolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: GitHubActions-Target-Policy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - s3:ListAllMyBuckets
              - s3:GetBucketLocation
            Resource: "*"
          - Effect: Allow
            Action:
              - s3:ListBucket
              - s3:GetObject
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::*
              - !Sub arn:${AWS::Partition}:s3:::*/*

それぞれのメリット・デメリット

GitHub Actionsのワークフローの書き方やクロスアカウント設定の観点から見ると、共通のIAM OIDC IDプロバイダーを用意することの利点はあまり感じられませんが、IAM OIDC IDプロバイダーが使用するIAMロールには「どのリポジトリからの実行か」を定義する必要があります。
将来的にリポジトリが増えることを考えると、複数の開発アカウントにあるIAM OIDC IDプロバイダー用のIAMロールを修正するのは大変です。そのため、IAM OIDC IDプロバイダーをどのように用意するかは、組織の運用方針によって異なるため、自分たちに最適な構成を選択する必要があります。

観点 アカウントごとに配置 共通アカウントに集約
ワークフローの記述 直接IAM Role を引き受ける。1ステップで書く。 共通アカウントからIAM Role を引き受けた後にAssumeRole。2ステップ書く。
開発アカウント追加時の対応 開発アカウントにIAM OIDC ID プロバイダーとIAM Role を作成 共通アカウントのIAM OIDC ID プロバイダー用のIAM Role に追記し、開発アカウントにIAM Role を新規作成
GitHubリポジトリ変更時の対応 全アカウントのIAM OIDC ID プロバイダー用 IAM Role を修正 共通アカウントのIAM OIDC ID プロバイダー用 IAM Role のみ修正

おわりに

本記事では、マルチアカウント環境におけるGitHub ActionsとAWSの連携方法として、IAM OIDC ID プロバイダーの2つの配置パターンを紹介しました。

「アカウントごとに配置」は構成がシンプルで環境の独立性が高く、「共通アカウントに集約」はリポジトリ変更時の管理が容易になります。 どちらが正解ということはなく、組織の規模や運用体制、今後の拡張計画に応じて選択することが重要です。

クラウド版では、環境の独立性とシンプルさを優先し、アカウントごとに配置する方式の採用を検討しています。

皆さんの環境に合った設計の参考になれば幸いです。