GitLab Secrets Manager ADR 012: JWT ドメインの分離

コンテキスト

GitLab による OpenBao の使用は、GitLab Rails が発行し OpenBao が検証する JWT のドメイン分離に依存しています。特に、GitLab CI は単一の署名鍵しか持っていないため、適切な認可制御を確保するためにクレームの違いに依存する必要があります。分離したいスコープがいくつかあります:

  1. 他の外部シークレットマネージャー向けトークン(例:Vault 向け)
    • 外部シークレット統合経由で発行される JWT トークンはカスタマイズ可能な aud クレームを持ち、ユーザーはここに OpenBao アドレスを手動で設定できます。これは aud だけではトークンを拒否できないことを意味し(iss と鍵マテリアルも一致するため)、パイプラインのシークレット取得ユースケースを sub だけで区別することも不十分であることを意味します。したがって、必須クレームとして secrets_manager_scope に依存する必要があります。
    • さらに、将来的にパイプライン定義へのクレームのカスタマイズが許可された場合に要件を明示的にするために、secrets_manager_scope が外部シークレットマネージャー統合トークンに添付されないようにする必要があります。
  2. 新しいネームスペースの作成や権限の割り当てなど、高い特権が必要な Rails アクションのトークン。多くの場合、ユーザーがリクエストを開始します。
    • このサブカテゴリとして、Rake タスクや Sidekiq タスクには直接のユーザー割り当てがないことが多いです。
  3. ユーザースコープのアクション(シークレットの更新や作成など)に使用するために Rails に内部的に発行されるトークン。
  4. パイプラインの実行のために発行されるトークン。

グループレベルのシークレットの導入により、2 つの異なるユースケースを追加で分離する必要があります:

  1. プロジェクトシークレット
  2. グループシークレット

決定

アクセスのスコープ設定に 2 つの主要なフィールドを使用します:

  1. デフォルトクレームである sub は、すべての JWT ロールにバインドされ、クロスパーパスリクエストを防ぎます。そのため、すべての用途にわたって一意のプレフィックスを維持する必要があります。現在追跡されているユースケースは以下のとおりです:
    1. システムスコープトークン向けの gitlab_secrets_manager
    2. ユーザースコープ JWT 向けの user:#{current_user.username}
    3. パイプライン JWT 向けの project_path:{group}/{project}:ref_type:{type}:ref:{branch_name}
  2. secrets_manager_scope:以下のリテラル文字列のいずれかを含む、容易に検証可能な多層防御クレームです:
    • privilegedauth/gitlab_rails_jwt/ のトップレベルマウントに対する高い特権のもの
    • pipeline:プロジェクト内で実行されているパイプラインで、プロジェクトまたはグループネームスペースからシークレットを取得する
    • user:プロジェクトまたはグループネームスペース内のユーザースコープトークン

このように、sub が一意のプレフィックスでない場合の、トークンスコープを検証するフォールバック方法を持ちます。

さらに、テナント、グループ、プロジェクトスコープの認証方式内では、以下のクレームに依存します:

  1. プロジェクトにスコープされる場合は project_id、または
  2. グループにスコープされる場合は group_id

特に、Rails はクレームを付与する前に、リクエストしているパイプラインまたはユーザーがこのプロジェクトに関連していることを検証する必要があります(外部シークレットマネージャー向けトークンに関する上記の注意事項を参照)。実際のポリシー決定は他のクレーム(例:user_idrole_idref_typeenvironment など)に基づいて行われるため、発行されたトークンは実際には OpenBao 内で権限が付与されない場合があります。つまり、Rails はプロジェクトとの関係を検証しますが(それは厳密に Rails データベースにあるため)、OpenBao はシークレットマネージャー内で付与された権限の唯一の信頼できる情報源であり続けます。

単一ロール、複数の用途

高い特権を持つ auth/gitlab_rails_jwt ロールに対して、主要な認可決定は subsecrets_manager_scope の組み合わせを中心に展開されます。project_idgroup_id などの値は存在する必要がありますが(またはユーザー駆動のアクションが特定の場所への場合には存在しなければなりません)、Rake タスクや潜在的にはマイグレーションや Sidekiq ジョブなどのシナリオでは、正確なユーザー情報が実際には存在しない場合があります。