OpenSSHのAuthorizedPrincipalsCommandによるユーザー検索

GitLab 11.2で導入されました

GitLabのデフォルトのSSH認証では、ユーザーがSSHトランスポートを使用する前にSSH公開キーをアップロードする必要があります。

特に、SSHキーがユーザーに発行された一時的なもので、発行から24時間後に失効するものである場合などです。

そのようなセットアップでは、常に新しい鍵をGitLabにアップロードするために、外部の自動化されたプロセスが必要になります。

caution
AuthorizedKeysCommand がフィンガープリントを受け付ける必要があるため、OpenSSH のバージョンは 6.9 以上が必要です。サーバー上のOpenSSHのバージョンを確認してください。

なぜ OpenSSH 証明書を使うのですか?

OpenSSH証明書を使うことで、GitLabのどのユーザーが鍵を所有しているかという情報はすべて鍵自体にエンコードされており、OpenSSH自体が、ユーザーがこれを偽造できないことを保証しています。

正しく設定すれば、ユーザーのSSHキーをGitLabにアップロードする必要がなくなります。

GitLab Shell経由でのSSH証明書ルックアップの設定

SSH 証明書の完全な設定方法はこのドキュメントの範囲外です。どのように動作するかはOpenSSH のPROTOCOL.certkeys (たとえばRedHat のドキュメント) を参照ください。

すでに SSH 証明書をセットアップしていて、CA のTrustedUserCAKeyssshd_config などに追加していると仮定します:

TrustedUserCAKeys /etc/security/mycompany_user_ca.pub

通常はTrustedUserCAKeysMatch User git の下に置くことはないでしょう。GitLab サーバーへのログインにも使われるからです。もしCAがGitLabのためだけに使われるのであれば、Match User git (後述)のセクションに置くことを検討してください。

そのCAが発行するSSH証明書は、例えばGitLab上のユーザーのユーザー名に対応する “key ID “を持っている必要があります(簡潔にするために出力を一部省略しています):

$ ssh-add -L | grep cert | ssh-keygen -L -f -

(stdin):1:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:[...]
        Signing CA: RSA SHA256:[...]
        Key ID: "aearnfjord"
        Serial: 8289829611021396489
        Valid: from 2018-07-18T09:49:00 to 2018-07-19T09:50:34
        Principals:
                sshUsers
                [...]
        [...]

技術的には厳密にはそうではありません。たとえば、prod-aearnfjord 通常ユーザーとしてサーバーにサインインする SSH 証明書 prod-aearnfjordであればそうなる可能性がありますが、その場合は私たちが提供するデフォルトを使うのではなく、独自のAuthorizedPrincipalsCommand を指定してマッピングを行う必要があります。

重要なのは、AuthorizedPrincipalsCommand が何らかの方法で “鍵ID” から GitLab のユーザー名にマッピングできなければならないということです。デフォルトのコマンドでは、この二つの間に 1=1 のマッピングがあると仮定しています。これは、デフォルトの公開鍵とユーザー名のマッピングのようなものに頼るのではなく、鍵そのものから GitLab のユーザー名を抽出できるようにするためです。

sshd_config 内部でgit ユーザー用にAuthorizedPrincipalsCommand を設定します。GitLabに同梱されているデフォルトのものを使えるといいですね:

Match User git
    AuthorizedPrincipalsCommandUser root
    AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers

このコマンドは次のような出力をします:

command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL}

ここで、{KEY_ID} はスクリプトに渡された%i 引数 (たとえば、aeanfjord) であり、{PRINCIPAL} はスクリプトに渡されたプリンシパル (たとえば、sshUsers) です。

sshUsers の部分をカスタマイズする必要があります。GitLab にサインインできる全ユーザーの鍵の一部であることが保証されているプリンシパルを指定するか、あるいはプリンシパルのリストを指定しなければなりません:

    [...]
    AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers windowsUsers

プリンシパルとセキュリティ

プリンシパルはいくつでも指定でき、sshd_config(5)AuthorizedPrincipalsFile ドキュメントで説明されているように、authorized_keys の複数行の出力に変換されます。

通常、OpenSSH でAuthorizedKeysCommand を使う場合、プリンシパルとはそのサーバーへのログインを許可された「グループ」のことです。しかし、GitLabではOpenSSHの要求に応えるためだけに使われるもので、事実上、”key ID “が正しいかどうかだけを気にしています。一旦それが抽出されると、GitLabはそのユーザーに対して独自のACLを強制します(例えば、そのユーザーがアクセスできるプロジェクトなど)。

そのため、許可する内容は大目に見てもかまいません。たとえば、そのユーザーが GitLab にアクセスできない場合は、無効なユーザーであることを示すメッセージとともにエラーが発生します。

authorized_keys ファイルとのやりとり

SSH 証明書はauthorized_keys ファイルと組み合わせて使用することができます。上記の設定に従ってauthorized_keys ファイルを設定しても、フォールバックとして機能します。

これはAuthorizedPrincipalsCommand がユーザーを認証できない場合、OpenSSH は~/.ssh/authorized_keys (またはAuthorizedKeysCommand) にフォールバックするからです。

ですから、データベースの SSH キーを高速に検索する方法と、 この方法を併用する理由があるかもしれません。一般的なユーザーには SSH 証明書を使い、デプロイ鍵は~/.ssh/authorized_keys フォールバックに頼ることになるでしょう。

しかし、一般的なユーザーはすべて高速パス(AuthorizedPrincipalsCommand )を使用し、 自動デプロイキーアクセスのみが~/.ssh/authorized_keys 、デプロイキーの数よりも一般的な ユーザー用のキーの数(特に更新された場合)の方が多いため、そのようなことをする必 要がないと感じるかもしれません。

その他のセキュリティ上の注意点

ユーザーは手動で SSH 公開キーをプロファイルにアップロードすることで SSH 証明書認証を回避することができます。この場合、~/.ssh/authorized_keys のフォールバック認証に依存します。現在のところ、これを防ぐ機能はありませんが、追加するためのオープンリクエストがあります。

このような制限は、例えばgitlab-shell-authorized-keys-check から返された発見された key-ID がデプロイ鍵であるかどうかをチェックするカスタムAuthorizedKeysCommand を提供することで、現在のところハックすることができます (デプロイ鍵でない鍵はすべて拒否されるはずです)。

SSHキーがないユーザーに関するグローバルな警告を無効にします。

デフォルトでは、GitLab は SSH キーをプロファイルにアップロードしていないユーザーに対して “You won’t be able to pull or push project code via SSH” という警告を表示します。

SSH証明書を使う場合、ユーザーが自分のSSHキーをアップロードすることは期待されていないので、これは逆効果です。

この警告をグローバルに無効にするには、”Application settings -> Account and limit settings” で “Show user add SSHキー message” 設定を無効にしてください。

この設定は特にSSH証明書を使用するために追加されましたが、他の理由で警告を非表示にしたい場合は、証明書を使用せずにオフにすることができます。