X.509証明書によるコミットとタグの署名
GitLab 12.8で導入されました。
X.509は、公開または非公開の秘密鍵基盤(PKI) によって発行される公開鍵証明書の標準フォーマットです。個人のX.509証明書は、S/MIME(Secure/Multipurpose Internet Mail Extensions)のような認証や署名の目的で使われます。しかし、GitもGPG(GnuPG、GNU Privacy Guard)と同様にX.509証明書によるコミットやタグの署名をサポートしています。主な違いは、開発者の署名が信頼できるかどうかをGitLabが判断する方法です:
- X.509の場合、ルート認証局がGitLabトラストストアに追加されます。(X.509の場合、ルート認証局がGitLabトラストストアに追加されます(トラストストアとは、信頼できるセキュリティ証明書のリポジトリです)。署名に必要な中間証明書と組み合わせることで、開発者の証明書は信頼できるルート証明書にチェーンバックすることができます。
- GPG については、開発者は自分のアカウントにGPG 鍵を追加します。
GitLabは独自の証明書ストアを使用するため、トラストチェーンを定義します。コミットやタグがGitLabによって検証されるには:
- 署名証明書のEメールアドレスがGitLabで認証されたEメールアドレスと一致する必要があります。
- GitLabインスタンスは、署名の証明書からGitLab証明書ストアの信頼できる証明書までの完全な信頼チェーンを確立できなければなりません。このチェーンには、署名で提供された中間証明書を含めることができます。作成者ルート証明書などの証明書をGitLab証明書ストアに追加する必要があるかもしれません。
- 署名時間は証明書の有効期間内である必要があり、通常は最長3年です。
- 署名時刻はコミット時刻と等しいか、それよりも遅い。
コミットのステータスが既に決定されデータベースに保存されている場合は、Rakeタスクを使用してステータスを再確認してください。トラブルシューティングのセクションを参照してください。GitLabはバックグラウンドワーカーで証明書の失効リストを毎日チェックします。
制限事項
- 
authorityKeyIdentifier、subjectKeyIdentifier、crlDistributionPointsを使用しない自己署名証明書には対応していません。RFC 5280に準拠したPKIからの証明書を使用することをお勧めします。
- 署名証明書の Subject Alternative Name リストに複数の電子メールがある場合、コミットの検証には最初のものだけが使用されます。
- 発行者証明書と署名証明書のX509v3 Subject Key Identifier(SKI) は40 文字でなければなりません。SKI が短いと GitLab でコミットが検証済みとして表示されません。また、短い Subject Key Identifier はプロジェクトにアクセスする際に‘An error occurred while loading commit signatures’ やHTTP 422 Unprocessable Entityエラーを引き起こす可能性があります。
署名付きコミットの設定
コミット、タグ、またはその両方に署名するには、以下の設定が必要です:
X.509キー・ペアの取得
あなたの組織が公開鍵基盤(PKI)を持っている場合、その PKI は S/MIME 鍵を提供します。PKI から S/MIME 鍵ペアが提供されていない場合は、自分で自己署名ペアを作成するか、ペアを購入します。
X.509証明書をGitに関連付けます。
X.509署名を利用するには、Git 2.19.0以降が必要です。Gitのバージョンは、git --version.
正しいバージョンであれば、Gitの設定に進むことができます。
Linux
Git があなたの鍵を署名に使うように設定します:
signingkey=$( gpgsm --list-secret-keys | egrep '(key usage|ID)' | grep -B 1 digitalSignature | awk '/ID/ {print $2}' )
git config --global user.signingkey $signingkey
git config --global gpg.format x509
Windows と MacOS
WindowsまたはMacOSを設定します:
- 
S/MIME Signをインストールします:
- インストーラをダウンロードします。
- MacOS上でbrew install smimesign。
 
- 
smimesign --list-keysを実行して証明書の ID を取得します。
- 
git config --global user.signingkey <ID>を実行し、<ID>を証明書の ID に置き換えて、署名鍵を設定します。
- 
このコマンドでX.509を設定します: git config --global gpg.x509.program smimesign git config --global gpg.format x509
コミットの署名と検証
X.509 証明書を Git に関連付けたら、コミットに署名することができます:
- 
Git のコミットを作成する際に、 -Sフラグを追加します:git commit -S -m "feat: x509 signed commits"
- 
GitLab にプッシュし、 --show-signatureフラグでコミットが検証されていることを確認します:git log --show-signature
- 
コミットするたびに -Sフラグを入力したくない場合は、 このコマンドを実行すると Git が毎回署名してくれます:git config --global commit.gpgsign true
タグへの署名と確認
X.509証明書をGitに関連づけたら、タグに署名を始めましょう:
- 
Git タグを作成する際に、 -sフラグを追加します:git tag -s v1.1.1 -m "My signed tag"
- 
GitLab にプッシュし、このコマンドでタグが署名されていることを確認してください: git tag --verify v1.1.1
- 
タグをつけるたびに -sフラグを入力したくない場合は、 このコマンドを実行すれば Git が毎回タグに署名してくれます:git config --global tag.gpgsign true
関連するトピック
トラブルシューティング
管理者権限のないコミッターの方は、署名済みコミットの検証に関する問題のリストをレビューしてください。このページにあるその他のトラブルシューティングについては、管理者権限が必要です。
コミットの再確認
GitLab はチェックしたコミットのステータスをデータベースに保存します。Rake タスクを使って、以前にチェックしたコミットのステータスをチェックすることができます。
変更したら、このコマンドを実行します:
sudo gitlab-rake gitlab:x509:update_signatures
主な検証チェック
このコードでは以下のキー・チェックを行い、すべてverified を返す必要があります:
- 
x509_certificate.nil?は偽であるべきです。
- 
x509_certificate.revoked?は偽であるべきです。
- 
verified_signatureは真であるべきです。
- 
user.nil?は偽であるべきです。
- 
user.verified_emails.include?(@email)は真であるべきです。
- 
certificate_email == @emailは真であるべきです。
コミットがなぜUnverified と表示されるのかを調べるには :
- 
Railsコンソールを起動します: sudo gitlab-rails console
- 
調査対象のプロジェクト(パスまたはID)と完全なコミットSHAを特定します。この情報を使って、他のチェックを実行するための signature:project = Project.find_by_full_path('group/subgroup/project') project = Project.find_by_id('121') commit = project.repository.commit_by(oid: '87fdbd0f9382781442053b0b76da729344e37653') signedcommit=Gitlab::X509::Commit.new(commit) signature=Gitlab::X509::Signature.new(signedcommit.signature_text, signedcommit.signed_text, commit.committer_email, commit.created_at)チェックの結果判明したイシューに対処するために変更を加えた場合は、Railsコンソールを再起動してチェックを最初からやり直してください。 
- 
コミットの証明書を確認します: signature.x509_certificate.nil? signature.x509_certificate.revoked?どちらのチェックも falseを返すはずです:> signature.x509_certificate.nil? => false > signature.x509_certificate.revoked? => false既知のイシューにより、これらのチェックは Validation failed: Subject key identifier is invalidで失敗します。
- 
署名の暗号チェックを実行します。コードは trueを返す必要があります:signature.verified_signatureもし falseを返したら、このチェックをさらに調査してください。
- 
コミットと署名のメールアドレスが一致していることを確認してください: - Railsコンソールに比較対象のメールアドレスが表示されます。
- 最後のコマンドはtrueを返す必要があります:
 sigemail=signature.__send__:certificate_email commitemail=commit.committer_email sigemail == commitemail既知のイシューがあります: Subject Alternative NameリストのSubject Alternative Name最初のメールだけがSubject Alternative Name比較されます。Subject Alternative NameリストをSubject Alternative Name表示Subject Alternative Nameするにはsignature.__send__ :get_certificate_extension,'subjectAltName'開発者のメールアドレスがリストの最初のものでない場合、このチェックは失敗し、コミットは unverifiedとマークされます。
- 
コミットのメールアドレスは GitLab のアカウントに関連づけられていなければなりません。このチェックは falseを返すはずです:signature.user.nil?
- 
メールアドレスがGitLabのユーザーに関連付けられているかチェックしてください。このチェックは #<User id:1234 @user_handle>のようなユーザーを返すはずです:User.find_by_any_email(commit.committer_email)nilを返した場合、メールアドレスはユーザーに関連付けられておらず、チェックは失敗します。
- 
開発者のメールアドレスが検証済みであることを確認します。このチェックは真を返さなければなりません: signature.user.verified_emails.include?(commit.committer_email)前のチェックが nilを返した場合、このコマンドはエラーを表示します:NoMethodError (undefined method `verified_emails' for nil:NilClass)
- 
検証ステータスはデータベースに保存されています。データベースのレコードを表示するには pp CommitSignatures::X509CommitSignature.by_commit_sha(commit.sha);nil前のチェックですべて正しい値が返された場合: - 
verification_status: "unverified"はデータベースレコードを更新する必要があることを示します。Rakeタスクを使用してください。
- 
[]はデータベースにまだレコードがないことを示しています。GitLab でコミットを探して署名をチェックし、結果を保存します。
 
- 
暗号化検証チェック
GitLabがverified_signature 、false と判断した場合は、Railsコンソールでその理由を調べてください。これらのチェックがsignature 存在 signatureする必要があります。前の主な検証チェックのステップをsignature 参照して signatureください。
- 
発行者をチェックせずに署名をチェックすると、 trueを返します:signature.__send__ :valid_signature?
- 
署名日時をチェックします。このチェックは trueを返さなければなりません:signature.__send__ :valid_signing_time?- コードは、コード署名証明書の有効期限を許可します。
- 
コミットは証明書の有効期間中で、コミットの日付スタンプ以降に署名されなければなりません。 not_before,not_afterを含むコミット時刻と証明書の詳細を表示します:commit.created_at pp signature.__send__ :cert; nil
 
- 
TLSの信頼が確立できることを含め、署名をチェックします。このチェックは trueを返す必要があります:signature.__send__(:p7).verify([], signature.__send__(:cert_store), signature.__send__(:signed_text))- 
これに失敗した場合は、信頼を確立するために必要な証明書が足りない場合は、GitLab証明書ストアに追加してください。 
- 
証明書を追加した後、(このトラブルシューティングの手順が成功したら)Rakeタスクを実行してコミットを再確認します。 
- 
署名を含む証明書を表示します: pp signature.__send__(:p7).certificates ; nil
 
- 
追加の中間証明書とルート証明書が証明書ストアに追加されていることを確認します。ウェブサーバでの証明書チェーンの構築方法との一貫性を保つため:
- コミットに署名する Git クライアントは、証明書とすべての中間証明書を署名に含めるようにしましょう。
- GitLab証明書ストアにはルート証明書のみを含める必要があります。
GitLabトラストストアからルート証明書を削除した場合、例えばそれが期限切れになった場合、そのルートにチェーンバックするコミット署名はunverifiedと表示されます。
