無料でビルドを開始
CircleCI.comアカデミーブログコミュニティサポート

ジョブでの OpenID Connect トークンの使用

1+ year ago3 min read
クラウド
このページの内容

CircleCI では、環境変数で OpenID Connect ID (OIDC) トークンを利用できます。 ジョブは、CircleCI に永続的な認証情報を保存することなく、このトークンを使って互換性のあるクラウドサービスにアクセスすることができます。

OpenID Connect の IDトークン利用可能

CircleCI OpenID Connect の IDトークンは、以下の環境変数で利用できます:

  • $CIRCLE_OIDC_TOKEN

  • $CIRCLE_OIDC_TOKEN_V2

クラウドサービスの設定

クラウドサービスのドキュメントで、ID プロバイダーの追加方法を確認してください。 たとえば、AWS の場合は「 OpenID Connect (OIDC) ID プロバイダーの作成」、Google Cloud Platform の場合は「 Workload Identity 連携の構成」を参照してください。

OpenID プロバイダーは、組織に一意のものです。 URL は https://oidc.circleci.com/org/<organization_id> で、organization_id は、組織を表す組織 ID (UUID) です。 CircleCI の組織 ID は、 CircleCI Web アプリ[Organization Settings (組織設定)] > [Overview (概要)] で確認できます。

CircleCI が発行した OpenID Connect ID トークンには、固定の audience が設定されています (下記表の aud を参照)。これも組織 ID です。

OpenID Connect ID トークンの形式

OpenID Connect ID トークンには、下記の標準 クレームが含まれています。

クレーム説明

iss

issuer: ジョブが実行されている CircleCI 組織に固有の issuer です。 値は、"https://oidc.circleci.com/org/<organization_id>" という文字列です。organization_id は、現在のジョブのプロジェクトの組織を表す UUID です。

sub

subject: CircleCI ジョブの実行者とその場所を識別します。 $CIRCLE_OIDC_TOKEN_V2 では、変更ソースの情報も含まれます。

$CIRCLE_OIDC_TOKEN の場合、この値は "org/<organization_id>/project/<project_id>/user/<user_id>" という文字列です。organization_idproject_iduser_id はそれぞれ、CircleCI の組織、プロジェクト、ユーザーを表す UUID です。 user は、このジョブを実行した CircleCI ユーザーです。

$CIRCLE_OIDC_TOKEN_V2 の場合、この値は "org/<organization_id>/project/<project_id>/user/<user_id>/vcs-origin/<vcs_origin>/vcs-ref/<vcs_ref>" という文字列です。organization_idproject_iduser_id はそれぞれ、CircleCI の組織、プロジェクト、ユーザーを表す UUID です。 user は、このジョブを実行した CircleCI ユーザーです。 vcs_originvcs_ref はそれぞれ、リポジトリの URL を指す文字列と、ジョブ実行のトリガーとなった変更を指す文字列です。

aud

audience: 現在は、固定の値 "ORGANIZATION_ID" で、ジョブのプロジェクトの組織を表す UUID を含む文字列です。

iat

time of issuance: トークンの作成時刻 (ジョブの開始直前の時刻) です。

exp

expiration time: iat から 1 時間後の値です。

OpenID Connect ID トークンには、ジョブに関する追加のメタデータを含む 追加クレームも含まれています。

追加クレームメタデータ

oidc.circleci.com/project-id

ジョブが実行されているプロジェクトの ID です。 値は、CircleCI プロジェクトを表す UUID を含む文字列です。

oidc.circleci.com/vcs-origin

パイプラインをトリガーしたリポジトリの URL です。 github.com/organization-123/repo-1 のような文字列になります。

oidc.circleci.com/vcs-ref

パイプラインのトリガーとなった変更のリファレンスです。 refs/heads/main のような文字列になります。

oidc.circleci.com/context-ids

ジョブで使用されるコンテキストを表す UUID を要素として持つ文字列の配列です。 現在サポートされているコンテキストは一つのみです。

oidc.circleci.com/ssh-rerun

CI ジョブが SSH 再実行機能を使用して開始されるかどうかを示す booleanです。

オープンソースプロジェクトでの OIDC

OIDCトークンは、Pull Request をフォークしたビルドにシークレットを渡す設定が有効な場合にのみ、フォークされたビルドに対して生成されます。 このオプションは Project settings > Advanced にあります。

もしOIDCトークンがフォーク用に生成されることを許可するのであれば、フォークされたビルドが必要とするリソース以外のリソースにアクセスすることを避けるために、ポリシーで oidc.circleci.com/vcs-origin クレームをチェックしなければなりません。

CircleCIでのオープンソースプロジェクトのビルドについての詳細は、 オープンソースプロジェクトのビルド ページを参照してください。

クラウドプロバイダーを使ったジョブの認証

次のセクションでは、Amazon Web Services (AWS) と Google Cloud Platform (GCP) を使用して CircleCI でジョブを認証する方法を説明します。

AWS

ここでは、AWS について下記の説明をします。

  • CircleCI の OIDC トークンを信頼するよう AWS アカウントのワンタイム設定を行う方法

  • AWS との連携に OIDC トークンを使用するジョブを実行する方法

また、この設定編に続く、 AWS ECRからOIDCでイメージを取り込む ノウハウもご覧ください。

CircleCI コンフィグファイルへの AWS の追加

AWS アカウントが CircleCI の OpenID Connect トークンを信頼するのを許可する必要があります。 これを行うには、Identity and Access Management (IAM) ID プロバイダーと AWS の IAM ロールを作成します。 IDプロバイダーの作成は、1回で設定が完了し、その後、関連するロールの管理方法を決定することができます。 ユースケースに合わせて、ポリシーを使ってロールの権限を更新したり、それぞれの用途に特化したロールを作成したりすることが可能です。

  1. AWS ドキュメントの「 OpenID Connect (OIDC) ID プロバイダーの作成」を参照し、指示に従います。 このページでは、管理コンソール(CLI)を使用した設定など、複数のオプションを紹介しています。  また、以下のものが必要になります:

    • Provider URL を求められたら、https://oidc.circleci.com/org/<your-organization-id> と入力します。organization_id には、CircleCI の組織 ID を入力します。

    • Audience: 組織 ID を入力してください

  2. IDプロバイダを作成すると、ADWコンソールの上部にバナーが表示され、Assign role というオプションが表示されます。 このボタンをクリックして新しいロールを作成するか、AWSドキュメントの ウェブ ID または OpenID Connect フェデレーション用のロールの作成セクションを参照して、 また、以下のものが必要になります:

    • 先ほど作成した Identity Provider

    • Audience は、先ほど入力した「組織 ID」のみを選択します。

    • Add Permissions ページでは、CircleCIジョブができること、できないことを指定できます。 これは AWS のベストプラクティスです。 また、 特定のユースケースに必要なものにパーミッションをロックダウンするために独自のポリシーを書くことができます。

CircleCI コンフィグファイルへの AWS の追加

IAM ロールのセットアップが完了したので、OIDC により AWS との認証を行う CircleCI ジョブを作成しましょう。 具体的には、CircleCI の AWS CLI Orb を使用して、一時キーの生成および OIDC を利用するプロファイルの設定を行います。

  1. .circleci/config で、aws-cli Orb をインポートします。

    version: 2.1
    
    orbs:
      aws-cli: circleci/aws-cli@3.1.5
  2. AWSサービスと対話する前に、aws-cli/setup コマンドを実行するようにジョブを構成します。 aws-cli/setup コマンドには、前述の手順で作成したロールに関連する role-arnaws-region を指定する必要があります。

    jobs:
      aws-example:
       environment:
          AWS_REGION: us-west-1
        docker:
          - image: cimg/aws:2022.06
        steps:
          - checkout
          # run the aws-cli/setup command from the orb
          - aws-cli/setup:
              role-arn: "arn:aws:iam::123456789012:role/OIDC-ROLE"
              aws-region: AWS_REGION
              # optional parameters
              profile-name: "OIDC-PROFILE"
              role-session-name: "example-session"
              session-duration: "1800"

    また、任意で、profile-namerole-session-namesession-duration を指定します。 profile-name を指定すると、指定したプロファイルに応じて一時キーとトークンが設定されます。 指定する profile-name は、他の AWS コマンドと揃える必要があります。 profile-name を指定しない場合、キーとトークンはデフォルトプロファイルにあわせてされます。

    さらに、role-session-name または session-duration を指定しない場合、それぞれデフォルト値の ${CIRCLE_JOB} (ジョブ名) と 3600 秒に設定されます。

以下に示すコンフィグファイルのサンプルでは、OIDC を使用するプロファイルを構成してからそのプロファイルで AWS ECR にログインするジョブを設定しています。 role-arn に適切な権限を設定していれば、このプロファイルを使用して S3 や EKS、ECS などの他の AWS コマンドも実行できます。

version: 2.1

orbs:
  aws-cli: circleci/aws-cli@3.1.5

jobs:
  aws-example:
   environment:
      AWS_REGION: us-west-1
    docker:
      - image: cimg/aws:2022.06
    steps:
      - checkout
      # run the aws-cli/setup command from the orb
      - aws-cli/setup:
          role-arn: "arn:aws:iam::123456789012:role/OIDC-ROLE"
          aws-region: AWS_REGION
          # optional parameters
          profile-name: "OIDC-PROFILE"
          role-session-name: "example-session"
          session-duration: "1800"
      - run:
        name: Log-into-AWS-ECR
        command: |
          # must use same profile specified in the step above
          aws ecr get-login-password --profile "OIDC-PROFILE"
workflows:
  OIDC-with-AWS:
    jobs:
      - aws-example:
          context: aws

高度な設定

CircleCI の OIDC token のクレーム形式を使って、AWS で CircleCI ジョブができることを制限することができます。

プロジェクトに応じたロールアクセスの制限

たとえば、特定のプロジェクトが特定の AWS リソースにのみアクセスできるようにする場合、特定のプロジェクトの CircleCI ジョブのみがそのロールを担えるように IAM ロールを制限できます。

これを行うには、IAM ロールの信頼ポリシーを編集して、選択したプロジェクトの OIDC トークンのみがその役割を担うようにします。 信頼ポリシーにより、どのような条件下でロールを担えるのかが決定します。

  1. CircleCI Web アプリで目的のプロジェクトのページに移動して、[Project Settings (プロジェクト設定)] > [Overview (概要)] でプロジェクト ID を確認します。

  2. ロールの信頼ポリシーに以下の条件を追加し、選択したプロジェクトのジョブのみがロールを担えるようにします。 organization_id には組織 ID、project_id にはプロジェクト ID を入力します。

    "StringLike": {
      "oidc.circleci.com/org/<organization_id>:sub": "org/<organization_id>/project/<project_id>/user/*"
    }

    これは StringLike を使って、選択したプロジェクトの CircleCI の OIDC トークンのサブクレームを照合します。 これで、他のプロジェクトのジョブは、このロールを担えないようになりました。

ブランチに応じたロールアクセスの制限

指定したブランチへのアクセスを制限することもできます。 以下に示す信頼ポリシーのサンプルでは、AssumeRoleWithWebIdentity アクションの使用を、ID が organization_id である GitHub 組織 (CircleCI 組織) my-orgmain ブランチで実行されるプロジェクトパイプラインのみに制限しています。 なお、sub クレームでは、$CIRCLE_OIDC_TOKEN_V2 形式を使用しています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.circleci.com/org/<organization_id>"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "oidc.circleci.com/org/<organization_id>:sub": "org/<organization_id>/project/*/user/*/vcs-origin/github.com/my-org/*/vcs-ref/refs/heads/main"
                }
            }
        }
    ]
}

Google Cloud Platform

ここでは、GCP について下記の説明をします。

  • CircleCI の OIDC トークンを信頼するよう GCP 設定のワンタイム設定を行う方法

  • GCP との連携に OIDC トークンを使用するジョブを実行する方法

Google Cloud CLI はコンフィグファイルを読み込みます。このファイルには Google Cloud で認証を行うために必要な情報が含まれます。 外部の ID プロバイダーについては Google Cloud のドキュメント で確認できます。

GCP のセットアップ

GCP 設定ファイルは GCP Web UI を使用してセットアップできます。 [Workload Identity Federation UI][Grant Access] に移動します。ここで求められる設定は、後からダウンロードできます。 CIRCLE_OIDC_TOKEN_FILE という名前のファイルを作成する必要があります。ここから Google Cloud が ID トークンを読み取ります (ファイル名は、credential_source の設定内容と一致していれば任意の名前にできます)。

CircleCI の組織 ID が必要になります。この ID を見つけるには、https://app.circleci.com/[CircleCI Web アプリ]で [Organization Settings (組織設定)] > [Overview (概要)] に移動します。

GCP Web UI の Grant Access セクションに移動したら、次の手順を実行して CircleCI を外部 ID プロバイダーとして追加します。

  1. IAM & Admin Panel に移動します。

  2. サイドパネルで [Workload Identity Federation] に移動します。

  3. [Add Provider] ボタンをクリックします。

  4. [Select a provider] ドロップダウンから [OpenID Connect (OIDC)] を選択して [Save] をクリックします。

  5. [Provider details] フォームに入力します。

    • JSON Web トークンの aud クレームが UUID (CircleCI 組織 ID) であるため、[Allowed audiences] を選択します。 audience は CircleCI 組織 ID にします。

    • issuer は https://oidc.circleci.com/org/<organization_id> です。organization_id には CircleCI 組織 ID を入力します。

  6. [Continue] をクリックしてプロバイダー属性を設定します。

    プロバイダー属性を設定すると、CircleCI のトークンに含まれるクレームを Google の "解釈" にマッピングできます。 例えば下記のようにします。

    google.subject

    attribute.project_id

    attribute.org_id

    assertion.aud

    assertion.sub

    assertion['oidc.circleci.com/project-id']

  7. IAM & Admin Panel の [Service Account] に移動して、サービスアカウントを作成して適切なアクセス許可を付与します。

  8. [Workload Identity Federation] に戻って表からプロバイダーを選択します。

  9. [Grant access] ボタンをクリックします。

  10. モーダルが表示され、作成したサービスアカウントをドロップダウンから選択します。 これが、トークンで使用されるアカウントで、関連付けられたすべてのアクセスが許可されます。

  11. [Select principals] で条件を追加するか、デフォルトのままにできます。

  12. [Save] をクリックします。 設定の実施とコンフィグファイルのダウンロードを求めるポップアップが表示されます。 このファイルは、[Connected Service Accounts] に移動すると後でダウンロードすることもできます。

  13. ダウンロードしたコンフィグファイルをリポジトリに保存します。 このファイルは CircleCI 設定で参照します。

コンフィグファイルのサンプルを以下に示します。 audience の次の情報がまだ設定されていないことに注意してください。

  • project_number (プロジェクト用に生成された一意の識別番号)

  • pool_id (ワークロード ID プールを参照する ID。circleci_oidc など)

  • provider_id (ワークロード ID プールプロバイダーを参照する ID。circleci など)

 {
  "type": "external_account",
  "audience": "//iam.googleapis.com/projects/<project_number>/locations/global/workloadIdentityPools/<pool_id>/providers/<provider_id>",
  "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
  "token_url": "https://sts.googleapis.com/v1/token",
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/circleci-test@incubator-344312.iam.gserviceaccount.com:generateAccessToken",
  "credential_source": {
    "file": "CIRCLE_OIDC_TOKEN_FILE",
    "format": {
      "type": "text"
    }
  }
}

この設定で、credential_sourceCIRCLE_OIDC_TOKEN_FILE ファイル内で ID トークンの検出を試みます。

トークンが API レスポンスに基づいている場合、JSON ファイルを読み取るように設定をセットアップすると便利です。 この場合、typejson に設定し、有効な path を指定する必要があります (例: response.id_token)。

  "credential_source": {
    "file": "CIRCLE_OIDC_TOKEN_FILE",
    "format": {
      "type": "json",
      "path": "response.id_token"
    }
  }

必要に応じて、次のスクリプトを実行して GCP コンフィグファイルを生成することもできます。

gcloud iam workload-identity-pools create-cred-config \
  "${GCP_WORKLOAD_IDENTITY_POOL_AUDIENCE}" \
  --output-file="${GCP_CREDENTIAL_CONFIGURATION_FILE}" \
  --service-account="${GCP_SERVICE_ACCOUNT_EMAIL}" \
  --credential-source-file="${GCP_CREDENTIAL_SOURCE_FILE}"

CircleCI コンフィグファイルへの GCP の追加

次のように実行して、$CIRCLE_OIDC_TOKENCIRCLE_OIDC_TOKEN_FILE という名前のファイルにエクスポートする必要があります。

echo $CIRCLE_OIDC_TOKEN >> CIRCLE_OIDC_TOKEN_FILE

次の環境変数を context に追加する必要もあります。

コンテキスト変数名

サンプル値

備考

GCP_PROJECT_ID

123456789012

GCP プロジェクト番号

GCP_WIP_ID

myworkloadpoolid

ワークロードの ID プールの ID

GCP_WIP_PROVIDER_ID

myproviderid

ワークロードの ID プールプロバイダー名

GCP_SERVICE_ACCOUNT_EMAIL

myserviceacct@myproject.iam.gserviceaccount.com

ユーザー管理サービスアカウント

次に、GCP をジョブに追加し、gcp-oidc-authenticate コマンドを使用して認証するサンプル設定の完全な例を示します。 この例では circleci/gcp-cli Orb を使用します。

version: 2.1

orbs:
  gcp-cli: circleci/gcp-cli@2.4.1

commands:
  gcp-oidc-generate-cred-config-file:
    description: "Authenticate with GCP using a CircleCI OIDC token."
    parameters:
      project_id:
        type: env_var_name
        default: GCP_PROJECT_ID
      workload_identity_pool_id:
        type: env_var_name
        default: GCP_WIP_ID
      workload_identity_pool_provider_id:
        type: env_var_name
        default: GCP_WIP_PROVIDER_ID
      service_account_email:
        type: env_var_name
        default: GCP_SERVICE_ACCOUNT_EMAIL
      gcp_cred_config_file_path:
        type: string
        default: /home/circleci/gcp_cred_config.json
      oidc_token_file_path:
        type: string
        default: /home/circleci/oidc_token.json
    steps:
      - run:
          command: |
            # Store OIDC token in temp file
            echo $CIRCLE_OIDC_TOKEN > << parameters.oidc_token_file_path >>
            # Create a credential configuration for the generated OIDC ID Token
            gcloud iam workload-identity-pools create-cred-config \
                "projects/${<< parameters.project_id >>}/locations/global/workloadIdentityPools/${<< parameters.workload_identity_pool_id >>}/providers/${<< parameters.workload_identity_pool_provider_id >>}"\
                --output-file="<< parameters.gcp_cred_config_file_path >>" \
                --service-account="${<< parameters.service_account_email >>}" \
                --credential-source-file=<< parameters.oidc_token_file_path >>

  gcp-oidc-authenticate:
    description: "Authenticate with GCP using a GCP credentials file."
    parameters:
      gcp_cred_config_file_path:
        type: string
        default: /home/circleci/gcp_cred_config.json
    steps:
      - run:
          command: |
            # Configure gcloud to leverage the generated credential configuration
            gcloud auth login --brief --cred-file "<< parameters.gcp_cred_config_file_path >>"
            # Configure ADC
            echo "export GOOGLE_APPLICATION_CREDENTIALS='<< parameters.gcp_cred_config_file_path >>'" | tee -a "$BASH_ENV"

jobs:
  gcp-oidc-defaults:
    executor: gcp-cli/default
    steps:
      - gcp-cli/install
      - gcp-oidc-generate-cred-config-file
      - gcp-oidc-authenticate
      - run:
          name: Verify that gcloud is authenticated
          environment:
            GCP_SERVICE_ACCOUNT_EMAIL: jennings-oidc-test@makoto-workbench.iam.gserviceaccount.com
          command: gcloud iam service-accounts get-iam-policy "${GCP_SERVICE_ACCOUNT_EMAIL}"

workflows:
  main:
    jobs:
      - gcp-oidc-defaults:
          name: Generate Creds File and Authenticate
          context:
          - gcp-oidc-dev

複数のサービスアカウントを同じ GCP プロジェクトから使用することも、複数の GCP プロジェクトから使用することもできます。 これらの方法と例の詳細は、CircleCI の サンプルリポジトリ で確認できます。


Suggest an edit to this page

Make a contribution
Learn how to contribute