This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
StatusAuthorsCoachDRIsOwning StageCreated
ongoing @igor.drozdov @stanhu devops create 2023-07-28

SSH証明書

要約

GitLab.comでは、顧客は自分の最上位グループ(後の組織)を取得します。自己管理に比べて、このレベルで組織全体の設定を管理する必要があります。

現在、SaaSで提供されているGitアクセスコントロールオプション(SSH、HTTPS)は、ユーザープロファイルで設定されたクレデンシャル(アクセストークン、SSHキー)に依存しています。ユーザープロファイルは組織のコントロール外にあるため、その鍵が秘密に保たれているかどうか、有効期限がポリシーに合っているかどうかを顧客が評価する方法はありません。また、Gitへのアクセス・フローにMFAを適用することもできないため、万が一鍵が流出した場合のダメージ・コントロールもほとんどできません。

顧客は、開発者が日常的に MFA を使って一時的な SSH 証明書を要求し、内部システムにアクセスできるようにするプロセスを用意しているかもしれません。SaaSで同じように作業できるようにするには、Gitアクセス制御の目的で、公開認証局(CA )ファイルをGitLab.com SaaSと共有する方法が必要です。

動機

  • GitLab.com SaaSで公開認証局(CA)ファイルをユーザーと共有できるようにし、Gitのアクセス制御を実現。
  • GitLabと、SSH証明書による認証をすでにサポートしている競合製品との間の製品ギャップを埋めます。

目標

本文書では、以下の要件を満たす機能を実装するためのアーキテクチャ設計を提案します:

  • 証明書の発行に使用するCA ファイル (CA.pub) の公開鍵をグループに追加できること。
  • CA で発行された証明書を使うと、グループやその祖先のプロジェクトに Git でアクセスできるようになります。
  • この証明書は、そのグループとその祖先以外のプロジェクトへの Git アクセスには使えません。

非目標

このドキュメントでは、SSH 証明書による認証をサポートするための Core 機能を提供することに焦点を当てています。潜在的な改善点についてはFollow Ups に記述されています。

提案

車々間通信

グループ管理者は、認証局ファイル (ssh-keygen -f CA) として使用する SSH キーペアを生成します:

  • 秘密鍵はユーザー証明書のイシューに使用されます。
  • 公開鍵は、ユーザー証明書を介してグループにアクセスを許可するために、グループに追加されます。

ユーザー証明書

グループ管理者はCA 秘密鍵を使ってユーザー証明書をイシューし、GitLab ユーザー名かユーザーのプライマリーメールを鍵のアイデンティティとして指定します:

ssh-keygen -s CA -I user@example.com -V +1d user-key.pub

その結果、以下のような構造のユーザー証明書が生成されます:

ssh-keygen -L -f ssh_host_ed25519_key-cert.pub

ssh_host_ed25519_key-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:dRVV49XJHt85X1seqr9xXyxyuuGTbtFV6Lbwlrx6BIQ
        Signing CA: RSA SHA256:UAcgUeGoXrs8WOT/N+bmqY2vB9145Mc5NaN1Y977NCI (using rsa-sha2-512)
        Key ID: "user@example.com"
        Serial: 1
        Valid: from 2023-07-31T18:20:00 to 2023-08-01T18:21:34
        Principals: (none)
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
  • Type はユーザー証明書のタイプです。GitLab Shellが受け入れるのはユーザー証明書のみで、他のタイプはすべて拒否されます。
  • Public Key はユーザーの公開鍵です。
  • Signing CA は、CA の公開鍵です。そのフィンガープリントは、ユーザー証明書に関連付けられているグループを見つけるために使用されます。
  • Key ID はユーザーのユーザー名かプライマリメールです。GitLabユーザーをユーザー証明書に関連付けるために使用されます。
  • Serial はユーザー証明書のシリアル番号です。同じCA によって作成された異なる証明書を区別するために使用できます。
  • Valid は有効期間を示します。この値はGitLab Shellによって検証されます:期限切れでまだ有効でないユーザー証明書は拒否されます。
  • Principals Critical OptionsExtensions はユーザー証明書に追加情報を埋め込むために使用されます。このフィールドは将来、ユーザー証明書に追加の制限を適用するために使用される可能性があります。

アプリケーションの動作

GitLab Shellは、SSH経由でGitLabインスタンスに送られるコマンドの処理を担当するプロジェクトです。ユーザがSSH接続を確立し公開キーで認証しようとすると、GitLab Shellは/authorized_keys エンドポイントに内部APIリクエストを送り、そのキーがGitLabユーザに関連付けられているかどうかを検出します。認証に証明書が使われている場合、GitLab Shellはそれを認識し、代わりに/authorized_certs へのリクエストを実行することができます。

  1. グループ管理者がCA.pub ファイルをグループに追加します。
  2. ユーザーがCA で署名された証明書を使用して認証を試みます。
  3. GitLab Shell はCA のフィンガープリントとユーザー ID(GitLab のユーザー名かプライマリメール)を/authorized_certs に送信します。
  4. GitLab RailsはフィCA.pub ンガープリントが追加さ CA.pubれたCA.pub グループとユーザーを CA.pub見つけます。CA とグループの間の一対一の関係を定義するフィンガープリントによってCA.pubCA.pubインスタンスで一意になります。
  5. GitLab Shell は確立された接続の名前空間フルパスを記憶します。
  6. GitLab Shell は/allowed ユーザーが特定のプロジェクトにアクセスできるかどうかのチェックが必要になるたびにエンドポイントに /allowedリクエストを送ります。/allowed 名前空間フルパスは /allowedエンド/allowed ポイントに渡さ /allowedれます。
  7. GitLab Railsは、ユーザーが証明書経由でこのプロジェクトにアクセスできるかどうかを判断するために、名前空間がプロジェクトの名前空間またはその祖先の一つと一致するかどうかをチェックします。
  8. 上記のチェックがすべて成功すると、ユーザーはプロジェクトにアクセスできるようになります。
sequenceDiagram User->>+GitLab Shell: Auth using SSH Certificate GitLab Shell->>+GitLab Rails: /authorized_certs?key=fingerprint-of-signing-key&user_identity=username-or-primary-email GitLab Rails-->>-GitLab Shell: responds with the namespace that configures the CA and the username of the user GitLab Shell-->>User: Authenticated successfully User->>+GitLab Shell: Git command to a specific project GitLab Shell->>+GitLab Rails: /allowed [namespace=namespace] GitLab Rails-->>-GitLab Shell: responds that the user is allowed to access a project in this namespace GitLab Shell-->>User: success

使用例

  1. CA.pub を設定するグループ外のプロジェクトにアクセスします。

    次のようなグループの階層があるとします。

    a/b/c/d/e/f
        |
        └/g/h/i
    
    • グループ管理者はCA.pubd に追加し、ユーザはCA によって署名された証明書を使用して認証されます。
    • ユーザーがa/b/c/d/e/f/project をクローンすると、a/b/c/d/e/project プロジェクトのフルパスとa/b/c/d 名前空間のフルパスを送信します。d はプロジェクトの名前空間の祖先であるため、ユーザーはプロジェクトのクローンを許可されます。
    • ユーザーがa/b/c/g/h/i/project をクローンする場合、d が祖先のリストにないため、ユーザーはプロジェクトのクローンを許可されません。
  2. CA.pub を設定するグループは、別のネームスペースに転送されます。

ネームスペースのフル・パスは接続ごとに保存されるため、既存の証明書はまだ有効です。ユーザーが再接続すると、/authorized_certs に別の要求が送信され、ネームスペースの新しいフル・パスが返されます。

オープンな質問

異なるプロジェクトへの複数のSSH証明書

ユーザーは異なるプロジェクトにアクセスするために異なる SSH 証明書を持っているかもしれません。ユーザーが SSH 接続を確立するとき、SSH クライアントは認証に成功するものを見つけるために、いくつかの候補を繰り返します。現在のアーキテクチャでは、ユーザーが別のプロジェクトにアクセスするためであっても、名前空間へのアクセスを提供する最初の証明書が受け入れられます。

使用例:

  1. ユーザーは、a およびb グループに対して有効な証明書を持っています。
  2. ユーザは、a を使用して正常に認証されます。
  3. ユーザーはb/project をクローンしようとして失敗します。

このシナリオの回避策は、SSH接続時に特定の証明書を使うようにGitを設定することです。.gitconfig ファイルに以下を追加します:

[core]
    sshCommand = ssh git@gitlab.com -i cert.pub

単一の証明書を無効にすることはできません

単一のユーザー証明書の失効は、この MVC の範囲外です。この機能を実装することは可能ですが、実現可能性については議論する必要があります。

この機能をサポートすると、実装とUI/UXが複雑になります。しかし、危殆化した証明書のリスクは、以下のアクションによって大幅に減らすことができます:

  • ユーザー証明書の有効期限。ドキュメントで強く推奨すべきです。
  • 現在のユーザー証明書をすべて失効させるCAのローテーション。
  • ユーザー証明書を使用できる IP アドレスを制限できるsource-address 機能の実装。

証明書は複数のGitLabインスタンスで使用することができます。

GitLabインスタンスに関する情報はユーザー証明書には埋め込まれません。つまり、KeyId の値がそれらのインスタンスで認識される限り、複数の GitLab インスタンスにまたがって使用することができます。

解決策

  • ユーザー証明書の使用を特定のインスタンスに制限するオプション・フィールドは、フォローアップでExtensions を使用して実装できます。extension:login@gitlab.com=username を指定する方がよりセキュアで柔軟なオプションですが、両方に対応できます。

CA を複数のグループで再利用することはできません。

CA.pub フィンガープリントは一意でなければならず、複数のグループで再利用することはできません。一対一の関係は、ユーザーがアクセスできる一つのグループを見つけることができるように設計によって選ばれています。

もう一つの選択肢は、Extensions またはCritical Options を使用してユーザー証明書に名前空間を埋め込むことです。

長所

  • CA 複数のグループで再利用できます。
  • ユーザー証明書は、どのグループにアクセスできるかを_尋ねる_のではなく、どのグループにアクセスできるかを_指示_します。

短所

  • ユーザー証明書フォーマットのカスタム要件が必要。
  • 他のグループがCA.pub を追加した場合、ユーザーは意図せずにそのグループへのアクセスを取得する可能性があります。

解決策

  • ユーザー証明書の使用を特定のグループに制限するオプション・フィールドは、フォローアップのExtensions またはCritical Options を使用して実装できます。CA は依然として再利用できませんが、ユーザー証明書を他のグループに使用することはできません。

反復計画

コンポーネントMilestoneグループ変更点
GitLab シェル16.3ソースコードGitLab ShellにSSH証明書を使った認証を実装する方法
GitLab Rails16.4ソースコードGitLab Rails API の内部エンドポイントauthorized_certs を実装して、設定するグループを探します。CA.pub
GitLab Rails16.4ソースコードグループのための GitLab Rails API エンドポイントを実装します。CA.pub
GitLab RailsNext 2-3 milestones認証と作成者許可追加/削除のためのグループ設定UXの実装CA.pub
GitLab RailsNext 2-3 milestones認証と作成者許可認証にSSH証明書のみを使用し、個人のSSHキーとアクセストークンを禁止するオプションを実装します。

フォローアップ

トピックに関連する機能ですが、このブループリントの範囲外です:

  • インスタンスやグループで Git over HTTPS を無効にすることで、認証に SSH 証明書だけを使うようにします。
  • インスタンスやグループでの個人SSHキーの使用を禁止することで、グループレベルのSSHキーのみを使うようにします。
  • ユーザー証明書の使用をIPアドレスのセットに制限するsource-address Critical Option
  • ユーザー証明書の利用をインスタンスのセットに制限するlogin@hostname=username Extensions の指定:ありがたい機能。
  • SSH証明書を使ったコミットへの署名: あると便利な機能。
  • 単一のユーザー証明書の失効。複雑なUI/UXが必要ですが、他の機能を使うことでリスクを大幅に軽減できます。