GitLab CI/CDジョブトークン
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
CI/CDパイプラインジョブの実行が近づくと、GitLabは一意のトークンを生成し、CI_JOB_TOKEN定義済み変数としてジョブで利用できるようにします。このトークンは、ジョブの実行中にのみ有効です。ジョブが完了すると、トークンアクセスは失効し、このトークンは使用できなくなります。
CI/CDジョブトークンを使用して、実行中のジョブから特定のGitLab機能に対して認証を行います。トークンは、パイプラインをトリガーしたユーザーと同じアクセスレベルを付与されますが、アクセスできるリソースはパーソナルアクセストークンよりも少なくなります。ユーザーは、コミットのプッシュ、手動ジョブのトリガー、スケジュールされたパイプラインのオーナーになるなどのアクションによってジョブを実行できます。このユーザーには、リソースにアクセスするために必要な権限を持つロールが付与されている必要があります。
ジョブトークンを使用してGitLabに対して認証し、別のグループやプロジェクトのリソース(ターゲットプロジェクト)にアクセスできます。デフォルトでは、ジョブトークンのグループまたはプロジェクトは、ターゲットプロジェクトの許可リストに追加する必要があります。
プロジェクトが公開または内部の場合、許可リストに登録されていなくても、一部の機能にはアクセスできます。たとえば、プロジェクトの公開パイプラインからアーティファクトをフェッチできます。このようなアクセスを制限することもできます。
ジョブトークンアクセス
CI/CDジョブトークンは、次のリソースにアクセスできます:
| リソース | 備考 |
|---|---|
| ブランチAPI | GET /projects/:id/repository/branchesエンドポイントにアクセスできます。 |
| コミットAPI | GET /projects/:id/repository/commits/:shaおよびGET /projects/:id/repository/commits/:sha/merge_requestsエンドポイントにアクセスできます。 |
| コンテナレジストリ | ジョブのプロジェクトに関連付けられたコンテナレジストリに対して認証するために、$CI_REGISTRY_PASSWORD定義済み変数として使用します。 |
| パッケージレジストリ | レジストリに対する認証に使用します。 |
| Terraformモジュールレジストリ | レジストリに対する認証に使用します。 |
| セキュアファイル | ジョブでセキュアファイルを使用するために、glab securefileコマンドで使用されます。 |
| コンテナレジストリAPI | ジョブのプロジェクトに関連付けられたコンテナレジストリに対してのみ認証できます。 |
| デプロイAPI | このAPIのすべてのエンドポイントにアクセスできます。 |
| 環境API | このAPIのすべてのエンドポイントにアクセスできます。 |
| ファイルAPI | GET /projects/:id/repository/files/:file_path/rawエンドポイントにアクセスできます。 |
| ジョブAPI | GET /jobエンドポイントのみにアクセスできます。 |
| ジョブアーティファクトAPI | ダウンロードエンドポイントのみにアクセスできます。 |
| マージリクエストAPI | GET /projects/:id/merge_requestsおよびGET /projects/:id/merge_requests/:merge_request_iidエンドポイントにアクセスできます。 |
| ノートAPI | GET /projects/:id/merge_requests/:merge_request_iid/notesおよびGET /projects/:id/merge_requests/:merge_request_iid/notes/:note_idエンドポイントにアクセスできます。 |
| パッケージAPI | このAPIのすべてのエンドポイントにアクセスできます。 |
| パイプライントリガートークンAPI | POST /projects/:id/trigger/pipelineエンドポイントのみにアクセスできます。 |
| パイプラインAPI | PUT /projects/:id/pipelines/:pipeline_id/metadataエンドポイントのみにアクセスできます。 |
| リリースリンクAPI | このAPIのすべてのエンドポイントにアクセスできます。 |
| リリースAPI | このAPIのすべてのエンドポイントにアクセスできます。 |
| リポジトリAPI | パブリックリポジトリのGET /projects/:id/repository/changelogエンドポイントのみにアクセスできます。 |
| タグAPI | GET /projects/:id/repository/tagsエンドポイントにアクセスできます。 |
権限をより細かく制御できるようにするための公開提案が存在します。
GitLab CI/CDジョブトークンのセキュリティ
ジョブトークンが漏洩した場合、CI/CDジョブをトリガーしたユーザーがアクセスできる非公開データへのアクセスに利用される可能性があります。このようなトークンの漏洩や不正利用を防ぐために、GitLabは以下を行います:
- ジョブログでジョブトークンをマスクする。
- ジョブの実行中にのみジョブトークンに権限を付与する。
さらに、Runnerを設定する際には、セキュリティを確保するために次の点に注意してください:
- マシンが再利用される場合は、Dockerの
privilegedモードを使用しない。 - 複数のジョブが同じマシンで実行される場合は、
shellexecutorを使用しない。
脆弱なGitLab Runner設定は、他のジョブからトークンを盗まれるリスクを増大させます。
プロジェクトへのジョブトークンアクセスを制御する
どのグループまたはプロジェクトがジョブトークンで認証し、プロジェクトのリソースの一部にアクセスできるかを制御できます。
デフォルトでは、ジョブトークンでのアクセスは、そのユーザーのプロジェクト内のパイプラインで実行されるCI/CDジョブのみに制限されています。別のグループまたはプロジェクトが、他のプロジェクトのパイプラインからのジョブトークンで認証できるようにするには、次の条件を満たす必要があります:
- ジョブトークンの許可リストにグループまたはプロジェクトを追加する必要があります。
- ジョブをトリガーするユーザーが、アクセス対象のプロジェクトのメンバーである必要があります。
- ユーザーには、アクションを実行するための権限が付与されている必要があります。
プロジェクトが公開または内部の場合、公開アクセスが許可されている一部のリソースには、任意のプロジェクトのジョブトークンでアクセスできます。このようなリソースを、許可リストに追加されたプロジェクトのみに制限することもできます。
GitLab Self-Managedの管理者は、この設定をオーバーライドして適用できます。この設定が適用されると、CI/CDジョブトークンは常にプロジェクトの許可リストに制限されます。
ジョブトークン許可リストにグループまたはプロジェクトを追加する
ジョブトークン許可リストにグループまたはプロジェクトを追加すると、ジョブトークンによる認証を通じてプロジェクトのリソースへのアクセスを許可できます。デフォルトでは、プロジェクトの許可リストにはそのプロジェクト自体のみが含まれています。クロスプロジェクトアクセスが必要な場合にのみ、グループまたはプロジェクトを許可リストに追加します。
許可リストにプロジェクトを追加しても、許可リストに登録されたプロジェクトのメンバーに追加の権限が付与されるわけではありません。許可リストに登録されたプロジェクトのジョブトークンを使用してプロジェクトにアクセスするには、プロジェクト内のリソースにアクセスする権限がそのユーザーにすでに付与されている必要があります。
たとえば、プロジェクトAの許可リストにプロジェクトBを追加するとします。これにより、プロジェクトB(許可されたプロジェクト)のCI/CDジョブは、CI/CDジョブトークンを使用してAPIコールを認証し、プロジェクトAにアクセスできるようになります。
前提要件:
- 現在のプロジェクトでメンテナー以上のロールを持っている必要があります。許可されたプロジェクトが内部または非公開の場合、そのプロジェクトではゲスト以上のロールが必要です。
- 許可リストに追加できるグループとプロジェクトの数は最大で200です。
グループまたはプロジェクトを許可リストに追加するには、次のようにします:
- 左側のサイドバーで、検索または移動先を選択して、プロジェクトを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > CI/CDを選択します。
- ジョブトークンの権限を展開します。
- Add group or project(グループまたはプロジェクトを追加)を選択します。
- 許可リストに追加するグループまたはプロジェクトへのパスを入力して、追加をクリックします。
APIを使用してグループまたはプロジェクトを許可リストに追加することもできます。
プロジェクトの許可リストに自動で入力する
ジョブトークン認証ログのデータを使用して、UIまたはRakeタスクでプロジェクトの許可リストを入力できます。
いずれの場合でも、GitLabは認証ログを使用して、許可リストに追加するプロジェクトまたはグループを判断し、それらのエントリを追加します。
このプロセスにより、プロジェクトの許可リストに最大200件のエントリが作成されます。認証ログに200件を超えるエントリが存在する場合、200件の制限以下に収まるように許可リストのコンパクションを行います。
UIを使用する場合
UIから許可リストを自動入力するには、次のようにします:
- 左側のサイドバーで、Search or go(検索または移動先)を選択して、プロジェクトを見つけます。
- 設定 > CI/CDを選択します。
- ジョブトークンの権限を展開します。
- 追加を選択し、ドロップダウンリストから認証ログのすべてのプロジェクトを選択します。
- アクションの確認を求めるダイアログが表示されたら、エントリーを追加を選択します。
このプロセスが完了すると、許可リストに認証ログのエントリが含まれるようになります。まだ設定されていない場合は、認証されたグループとプロジェクトが、このプロジェクトと許可リスト内のグループとプロジェクトのみに設定されます。
Rakeタスクを使用する場合
Railsコンソールへのアクセス権が付与されているGitLab管理者は、Rakeタスクを実行して、インスタンス上のすべてのプロジェクトまたは一部のプロジェクトの許可リストを自動的に入力できます。このタスクにより、認証されたグループとプロジェクト設定も、このプロジェクトと許可リスト内のグループとプロジェクトのみに指定されます。
ci:job_tokens:allowlist:autopopulate_and_enforce Rakeタスクには、次の設定オプションがあります:
PREVIEW: ドライランを実行し、実行予定のステップを出力します。データは変更しません。ONLY_PROJECT_IDS: 指定されたプロジェクトID(最大1000個のID)のみの移行を実行します。EXCLUDE_PROJECT_IDS: 指定されたプロジェクトID(最大1000個のID)以外の、インスタンス上のすべてのプロジェクトの移行を実行します。
ONLY_PROJECT_IDSとEXCLUDE_PROJECT_IDSを同時に使用することはできません。
次に例を示します:
ci:job_tokens:allowlist:autopopulate_and_enforce PREVIEW=trueci:job_tokens:allowlist:autopopulate_and_enforce PREVIEW=true ONLY_PROJECT_IDS=2,3ci:job_tokens:allowlist:autopopulate_and_enforce PREVIEW=true EXCLUDE_PROJECT_IDS=2,3ci:job_tokens:allowlist:autopopulate_and_enforceci:job_tokens:allowlist:autopopulate_and_enforce ONLY_PROJECT_IDS=2,3ci:job_tokens:allowlist:autopopulate_and_enforce EXCLUDE_PROJECT_IDS=2,3
Rakeタスクを実行するには、次のようにします:
sudo gitlab-rake ci:job_tokens:allowlist:autopopulate_and_enforcesudo -u git -H bundle exec rake ci:job_tokens:allowlist:autopopulate_and_enforce許可リストのコンパクション
許可リストのコンパクションアルゴリズム:
- 認証ログをスキャンして、複数のプロジェクトで最も近い共通グループを特定します。
- 複数のプロジェクトレベルのエントリを、単一のグループレベルのエントリに統合します。
- このように統合されたエントリを使用して、許可リストを更新します。
たとえば、次のような許可リストがあるとします:
group1/group2/group3/project1
group1/group2/group3/project2
group1/group2/group4/project3
group1/group2/group4/project4
group1/group5/group6/project5コンパクションアルゴリズム:
次のようにリストをコンパクションします:
group1/group2/group3 group1/group2/group4 group1/group5/group6許可リストが200件の上限を超えている場合、アルゴリズムは再度コンパクションします:
group1/group2 group1/group5それでも許可リストが200件の上限を超えている場合、アルゴリズムはさらにコンパクションを続けます:
group1
このプロセスは、許可リストのエントリ数が200件以下になるまで実行されます。
公開プロジェクトまたは内部プロジェクトのジョブトークンのスコープを制限する
許可リストに含まれていないプロジェクトでも、ジョブトークンを使用して公開または内部プロジェクトに対して認証し、次の操作を行えます:
- アーティファクトのフェッチ。
- コンテナレジストリへのアクセス。
- パッケージレジストリへのアクセス。
- リリース、デプロイ、環境へのアクセス。
- リポジトリにアクセスします。
各機能をプロジェクトメンバーのみに表示されるよう設定することで、これらのアクションへのアクセスを、許可リストに含まれるプロジェクトのみに制限できます。
前提要件:
- プロジェクトのメンテナーロールを持っている必要があります。
機能をプロジェクトメンバーのみが表示できるように設定するには、次のようにします:
- 左側のサイドバーで、検索または移動先を選択して、プロジェクトを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > 一般を選択します。
- 可視性、プロジェクトの機能、権限を展開します。
- アクセスを制限する機能の表示レベルをOnly project members(プロジェクトメンバーのみ)に設定します。
- アーティファクトをフェッチする機能は、CI/CDの表示レベルの設定によって制御されます。
- 変更を保存を選択します。
すべてのプロジェクトから自分のプロジェクトへのアクセスを許可する
- 提供形態: GitLab Self-Managed、GitLab Dedicated
トークンのアクセス制限と許可リストを無効にすると、セキュリティリスクにつながります。悪意のあるユーザーが、許可されていないプロジェクトで作成済みのパイプラインを侵害しようとする可能性があります。パイプラインがいずれかのメンテナーによって作成された場合、プロジェクトへのアクセスを試みるためにジョブトークンが悪用される可能性があります。
CI/CDジョブトークン許可リストを無効にすると、どのプロジェクトのジョブからでも、ジョブトークンを使用してプロジェクトにアクセスできるようになります。パイプラインをトリガーするユーザーには、プロジェクトにアクセスする権限が必要です。この設定を無効にするのはテストや同様の目的に限定し、可能な限り速やかに再度有効にする必要があります。
このオプションを利用できるのは、Enable and enforce job token allowlist for all projects(全プロジェクトでジョブトークン許可リストを有効にして適用する)設定が無効になっているGitLab Self-ManagedまたはGitLab Dedicatedインスタンスのみです。
前提要件:
- プロジェクトのメンテナー以上のロールを持っている必要があります。
ジョブトークン許可リストを無効にするには、次のようにします:
- 左側のサイドバーで、検索または移動先を選択して、プロジェクトを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > CI/CDを選択します。
- ジョブトークンの権限を展開します。
- 認証されたグループとプロジェクトで、全グループとプロジェクトを選択します。
- (推奨)テストが完了したら、This project and any groups and projects in the allowlist(このプロジェクトと許可リスト内のグループとプロジェクトのみ)を選択して、ジョブトークン許可リストを再度有効にします。
この設定は、GraphQL(inboundJobTokenScopeEnabled)またはREST APIでも変更できます。
プロジェクトリポジトリへのGitプッシュリクエストを許可する
CI/CDジョブトークンで認証されたGitプッシュリクエストを許可するようにプロジェクトを構成できます。この設定はデフォルトでオフになっています。
この設定をオンにすると、プロジェクトパイプラインで実行されるCI/CDジョブによって生成されたトークンのみが、プロジェクトにプッシュできます。許可リスト内の他のプロジェクトまたはグループからのジョブトークンを使用しても、プロジェクトにプッシュすることはできません。
ジョブトークンを使用してプロジェクトにプッシュすると、CIパイプラインはトリガーされません。ジョブトークンには、ジョブを開始したユーザーと同じアクセス権が付与されます。
semantic-releaseツールを使用している場合、リポジトリへのGitプッシュリクエストを許可する設定が有効になっていると、トークンは、構成されている場合は、GitLabパーソナルアクセストークンよりも優先されます。このエッジケースの解決を追跡する未解決のイシューがあります。
前提要件:
- プロジェクトのメンテナー以上のロールを持っている必要があります。
プロジェクトで生成されたジョブトークンにプロジェクトのリポジトリにプッシュする権限を付与するには、次のようにします:
- 左側のサイドバーで、検索または移動先を選択して、プロジェクトを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > CI/CDを選択します。
- ジョブトークンの権限を展開します。
- 権限セクションで、リポジトリへのGitプッシュリクエストを許可するを選択します。
この設定は、API(REST API)のci_push_repository_for_job_token_allowedパラメータ (ci_push_repository_for_job_token_allowed) を使用して制御することもできます。
ジョブトークンの詳細なアクセス許可設定
詳細なアクセス許可を使用して、制限された一連のREST APIエンドポイントへのアクセスを明示的に許可できます。詳細については、CI/CDジョブトークンの詳細なアクセス許可設定を参照してください。このイシューに関するフィードバックをお寄せください。
ジョブトークンを使用する
非公開プロジェクトのリポジトリをgit cloneする
ジョブトークンを使用すると、CI/CDジョブで認証を行い、非公開プロジェクトからリポジトリのクローンを作成できます。gitlab-ci-tokenをユーザーとして使用し、ジョブトークンの値をパスワードとして使用します。次に例を示します:
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/<namespace>/<project>HTTPSプロトコルがグループ、プロジェクト、またはインスタンスの設定によって無効になっている場合でも、このジョブトークンを使用してリポジトリのクローンを作成できます。
REST APIリクエストを認証する
ジョブトークンを使用して、許可されたREST APIエンドポイントに対するリクエストを認証できます。次に例を示します:
curl --verbose --request POST --form "token=$CI_JOB_TOKEN" --form ref=master "https://gitlab.com/api/v4/projects/1234/trigger/pipeline"さらに、リクエストでジョブトークンを渡す有効な方法はいくつかあります:
- フォーム:
--form "token=$CI_JOB_TOKEN" - ヘッダー:
--header "JOB-TOKEN: $CI_JOB_TOKEN" - データ:
--data "job_token=$CI_JOB_TOKEN" - URLのクエリ文字列:
?job_token=$CI_JOB_TOKEN
ジョブトークンを使用して、GraphQLエンドポイントへのリクエストを認証することはできません。
ジョブトークン認証ログ
他のどのプロジェクトがCI/CDジョブトークンを使用して自分のプロジェクトに対して認証しているかは、認証ログで追跡できます。ログを確認するには、以下を実行します:
- 左側のサイドバーで、検索または移動先を選択して、プロジェクトを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > CI/CDを選択します。
- ジョブトークンの権限を展開します。認証ログセクションには、ジョブトークンで認証してプロジェクトにアクセスした他のプロジェクトのリストが表示されます。
- オプション。認証ログ全体をCSV形式でダウンロードするには、CSVをダウンロードをクリックします。
認証ログには、最大100件の認証イベントが表示されます。イベント数が100件を超える場合は、CSVファイルをダウンロードしてログを確認してください。
プロジェクトへの新しい認証が認証ログに表示されるまで、最長5分かかる場合があります。
CI/CDトークンのレガシー形式を使用する
GitLab 19.0以降、CI/CDジョブトークンはデフォルトでJWT(JSON Webトークン)標準を使用しています。プロジェクトのトップレベルグループを設定すると、プロジェクトでレガシー形式を引き続き使用できます。この設定が利用できるのは、GitLab 20.0リリースまでです。
CI/CDトークンのレガシー形式を使用するには、次のようにします:
- 左側のサイドバーで、検索または移動先を選択して、グループを見つけます。新しいナビゲーションをオンにしている場合、このフィールドは上部のバーにあります。
- 設定 > CI/CDを選択します。
- 一般パイプラインを展開します。
- CI/CDジョブトークンのJWTフォーマットを有効にするをオフにします。
これにより、CI/CDトークンがレガシー形式を使用するようになります。後ほどJWT形式を再び使用する場合は、この設定を再度有効にします。
トラブルシューティング
CIジョブトークンの失敗は以下のとおり、通常、404 Not Foundなどの応答として表示されます:
許可されていないGitクローン:
$ git clone https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.com/fabiopitino/test2.git Cloning into 'test2'... remote: The project you were looking for could not be found or you don't have permission to view it. fatal: repository 'https://gitlab-ci-token:[MASKED]@gitlab.com/<namespace>/<project>.git/' not found許可されていないパッケージのダウンロード:
$ wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/1234/packages/generic/my_package/0.0.1/file.txt --2021-09-23 11:00:13-- https://gitlab.com/api/v4/projects/1234/packages/generic/my_package/0.0.1/file.txt Resolving gitlab.com (gitlab.com)... 172.65.251.78, 2606:4700:90:0:f22e:fbec:5bed:a9b9 Connecting to gitlab.com (gitlab.com)|172.65.251.78|:443... connected. HTTP request sent, awaiting response... 404 Not Found 2021-09-23 11:00:13 ERROR 404: Not Found.許可されていないAPIリクエスト:
$ curl --verbose --request POST --form "token=$CI_JOB_TOKEN" --form ref=master "https://gitlab.com/api/v4/projects/1234/trigger/pipeline" < HTTP/2 404 < date: Thu, 23 Sep 2021 11:00:12 GMT {"message":"404 Not Found"} < content-type: application/json
CI/CDジョブトークン認証の問題を解決する際は、以下の点に注意する必要があります:
- プロジェクトごとにスコープ設定を切り替えるには、GraphQLミューテーションサンプルを利用できます。
- このコメントは、BashとcURLでGraphQLを使用して、以下を行う方法を説明しています:
- 受信トークンのアクセススコープを有効にする。
- プロジェクトAからプロジェクトBへのアクセス権を付与する、またはBをAの許可リストに追加する。
- プロジェクトのアクセス権を削除する。
- ジョブがもはや実行されていない場合、消去された場合、またはプロジェクトが削除処理中の場合、CIジョブトークンは無効になります。
JWT形式のジョブトークンのエラー
CI/CDジョブトークンのJWT形式には、既知の問題がいくつかあります。
EC2 Fargate RunnerカスタムexecutorのError when persisting the task ARN.エラー
EC2 Fargateカスタムexecutorの0.5.0以前のバージョンにはバグがあります。この問題により、以下のエラーが発生します:
Error when persisting the task ARN. Will stop the task for cleanup
この問題を修正するには、Fargateカスタムexecutorのバージョン0.5.1以降にアップグレードしてください。
base64エンコードのinvalid character '\n' in string literalエラー
base64を使用してジョブトークンをエンコードすると、invalid character '\n'エラーが発生する場合があります。
これは、base64コマンドのデフォルトの動作では、79文字を超える文字列は折り返されるためです。ジョブ実行中に、たとえばecho $CI_JOB_TOKEN | base64を使用してJWT形式のジョブトークンをbase64でエンコードすると、そのトークンは無効になります。
この問題を修正するには、base64 -w0を使用してトークンの自動折り返しを無効にします。