SSL設定

利用可能なSSL構成タスク

Omnibus-GitLabは、SSL設定に関するいくつかの一般的なユースケースをサポートしています。

  1. GitLab インスタンスサービスへのhttps 接続を許可します。
  2. 外部リソース接続用の公開証明書バンドルの設定

ホストサービス

管理者は、GitLabサービスがサポートするどのような方法でもセキュアhttpを有効にすることができます。

Service Manual SSL Let’s Encrypt
Primary GitLab Instance Domain Yes Yes
Container Registry Yes Yes
Mattermost Yes Yes
GitLab Pages Yes No

Let’s Encryptインテグレーション

GitLabはLet’s Encryptとインテグレーションできます。

プライマリGitLabインスタンス

  • GitLab 10.5で導入され、デフォルトでは無効になっています。
  • GitLab 10.7以降では、httpsプロトコルでexternal_url 、証明書が設定されていない場合、デフォルトで有効になります。
注意: Let’s Encrypt の検証を正しく動作させるためには、検証を実行する Let’s Encrypt サーバがポート 80 と 443 にアクセスできる必要があります。 また、現在のところ、検証は標準以外のポートでは動作しないことに注意してください。
注意:GitLab 10.7以降にインストールまたはアップグレードする管理者で、Let’s Encryptを使用する予定がない場合は、/etc/gitlab/gitlab.rbletsencrypt['enable'] = false を無効に設定してください。

/etc/gitlab/gitlab.rb に以下のエントリを追加し、プライマリドメインのLet’s Encryptサポートを有効にします:

letsencrypt['enable'] = true                      # GitLab 10.5 and 10.6 require this option
external_url "https://gitlab.example.com"         # Must use https protocol
letsencrypt['contact_emails'] = ['foo@email.com'] # Optional
メンテナンスのヒントLet’s Encryptが発行する証明書は、90 日ごとに有効期限が切 れます。オプションのcontact_emailsを設定すると、有効期限が近づくと、設定したアドレスに有効 期限警告が送信されます。

GitLab コンポーネント

GitLab 11.0で導入されました。

基本的なLet’s Encryptインテグレーションを有効にし、/etc/gitlab/gitlab.rb を変更する手順に従ってください:

registry_external_url "https://registry.example.com"     # container registry, must use https protocol
mattermost_external_url "https://mattermost.example.com" # mattermost, must use https protocol
#registry_nginx['ssl_certificate'] = "path/to/cert"      # Must be absent or commented out
アンダーフードLet’s Encrypt証明書は、GitLab のプライマリインスタンスを証明書のプライマリ名として作成されます。 レジストリなどの追加サービスは、同じ証明書の代替名として追加されます。 上の例では、プライマリドメインがgitlab.example.com で、レジストリドメインがregistry.example.comであることに注意しましょう。 管理者は、ワイルドカード証明書の設定について心配する必要はありません。

Let’s Encryptの自動更新

GitLab10.7 で導入されました

注意:GitLab 12.1以降にインストールまたはアップグレードする管理者で、独自のLet’s Encrypt証明書を使う予定のある人は、/etc/gitlab/gitlab.rbletsencrypt['enable'] = false を設定し、自動更新を無効にしてください。そうしないと、gitlab-ctl reconfigure が証明書を更新しようとして上書きしてしまう可能性があります。

デフォルトのインストールでは、4日目の午前0時以降に更新がスケジュールされます。分数は、アップストリームのLet's Encrypt サーバーの負荷を分散するために、external_url の値によって決定されます。

/etc/gitlab/gitlab.rbに以下を追加することで、更新時間を明示的に設定できます:

# This example renews every 7th day at 12:30
letsencrypt['auto_renew_hour'] = "12"
letsencrypt['auto_renew_minute'] = "30"
letsencrypt['auto_renew_day_of_month'] = "*/7"

自動更新を無効にするには、/etc/gitlab/gitlab.rb

letsencrypt['auto_renew'] = false

手動によるLet’s Encryptの更新

Let’s Encrypt証明書を手動で更新するには、以下の方法を使用します。 手動で以下のコマンドのいずれかを使用して手動で更新します:

sudo gitlab-ctl reconfigure
sudo gitlab-ctl renew-le-certs
注意:GitLab 12.1以降では、Let’s Encrypt証明書を更新しようとします。独自のLet’s Encrypt証明書を使用する予定がある場合は、/etc/gitlab/gitlab.rbletsencrypt['enable'] = falseを設定し、インテグレーションを無効にする必要があります。そうしないと、更新によって証明書が上書きされる可能性があります。
ヒント上記のコマンドはroot権限を必要とし、証明書の有効期限が近い場合にのみ更新を生成します。 更新中にエラーが発生した場合は、アップストリームのレート制限を考慮してください。

外部リソースへの接続

環境によっては、様々なタスクのために内部リソースに接続することがあります。 Omnibus-GitLabでは、これらの接続にセキュリティhttp (https) を使用することができます。

デフォルト設定

Omnibus-GitLabは、証明書の信頼性を検証するために使用される信頼できるルート認証局の公式CAcert.orgコレクションを同梱しています。

その他の作成者

Omnibus GitLabは、自己署名証明書による外部サービスとの接続をサポートしています。

互換性ノートカスタム証明書はGitLab 8.9で導入されました。
追加情報自己署名証明書を使用するインストールでは、Omnibus-GitLabはこれらの証明書を管理する方法を提供します。 この仕組みの技術的な詳細については、このページの下部にある詳細を参照してください。

カスタム公開証明書のインストール

注意:c_rehash に依存する証明書を適切にシンボリックリンクするには、Perl インタプリタが必要です。Perl は現在Omnibus GitLab にはバンドルされていません。
  1. を生成します。 PEMまたは DERエンコードされた公開証明書を作成します。
  2. 公開証明書ファイルのみを/etc/gitlab/trusted-certs ディレクトリにコピーします。
  3. gitlab-ctl reconfigureを実行します。
注意:カスタム証明書チェーンを使用する場合、ルート証明書および/または中間証明書は、c_rehash が最初の証明書のみのハッシュを作成するため/etc/gitlab/trusted-certs の別々のファイルに入れる必要があります。

トラブルシューティング

便利なOpenSSLデバッグコマンド

時には、SSL証明書チェーンをソースで直接見ることで、より良いイメージを得るのに役立つことがあります。 これらのコマンドは診断とデバッグのためのツールの標準OpenSSLライブラリの一部です。

注:GitLabはすべてのGitLabライブラリがリンクされるOpenSSLの独自のカスタムコンパイルされたバージョンを含んでいます。 このOpenSSLバージョンを使って以下のコマンドを実行することが重要です。
  • ホストに HTTPS でテスト接続を行います。HOSTNAME を GitLab の URL(HTTPS を除く)に置き換え、port を HTTPS 接続を提供するポート(通常は 443)に置き換えてください:

     echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port
    

    echo コマンドはサーバーに NULL リクエストを送り、追加入力を待たずに接続を閉じます。HOSTNAME:port をリモートホストのドメインとポート番号に置き換えることで、同じコマンドをリモートホスト(例えば、外部リポジトリをホストしているサーバー)のテストに使うことができます。

    このコマンドの出力は、証明書チェーン、サーバーが提示する公開証明書、検証や接続エラーが発生した場合のエラーを表示します。 これにより、SSL設定に問題がないかすぐにチェックできます。

  • x509/path/to/certificate.crt を証明書のパスに置き換えてください:

     /opt/gitlab/embedded/bin/openssl x509 -in /path/to/certificate.crt -text -noout
    

    例えば、GitLabは自動的にLet’s Encryptから取得した証明書を/etc/gitlab/ssl/hostname.crt。そのパスを指定してx509 コマンドを使えば、証明書の情報(例えば、ホスト名、発行者、有効期間など)を素早く表示することができます。

    証明書に問題がある場合、エラーが発生します。

  • サーバから証明書を取得し、それをデコードする 上記の両方のコマンドを組み合わせて、サーバのSSL証明書を取得し、それをテキストにデコードします:

     echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port | /opt/gitlab/embedded/bin/openssl x509 -text -noout
    

OpenSSLを使ったSSL問題のトラブルシューティングの例については、SSLのトラブルシューティングのドキュメントを参照してください。

よくあるSSLエラー

  1. SSL certificate problem: unable to get local issuer certificate

    このエラーは、クライアントがルートCAを取得できないことを示しています。 これを解決するには、クライアントで接続しようとしているサーバーのルートCAを信頼するか、接続しようとしているサーバーの証明書を修正して、完全な連鎖証明書を提示します。

    注:クライアントが接続する際のSSLエラーを防ぐために、完全な証明書チェーンを使用することを推奨します。 完全な証明書チェーンの順序は、最初にサーバー証明書、次にすべての中間証明書、最後にルートCAで構成されるべきです。
  2. unable to verify the first certificate

    このエラーは、サーバによって不完全な証明書チェーンが提示されていることを示しています。 このエラーを修正するには、サーバの証明書を完全なチェーン証明書に置き換える必要があります。 完全な証明書チェーンの順序は、最初にサーバ証明書、次にすべての中間証明書、最後にルートCAで構成される必要があります。

  3. certificate signed by unknown authority

    このエラーは、クライアントが証明書またはCAを信頼していないことを示しています。 このエラーを修正するには、サーバに接続するクライアントが証明書またはCAを信頼する必要があります。

  4. SSL certificate problem: self signed certificate in certificate chain

    このエラーは、クライアントが証明書またはCAを信頼していないことを示しています。 このエラーを修正するには、サーバに接続するクライアントが証明書またはCAを信頼する必要があります。

で書かれた Git-LFS とその他の組み込みサービス ゴラン語不明な作成者によって署名されたカスタム証明書のレポート

注:GitLab 11.5では、組み込みgolangアプリが自動的に標準のGitLab証明書ディレクトリを使うようになったため、以下の回避策は必要なくなりました。

で書かれたgitlab-workhorse やその他のサービスです。 ゴランcrypto/tlsライブラリを使用しています。 のcrypto/tlsライブラリを使います。の crypto/tls ライブラリを使います。

/etc/gitlab/gitlab.rb に以下のエントリーを追加し、レポーターが報告したイシューを回避してください:

gitlab_workhorse['env'] = {
  'SSL_CERT_DIR' => '/opt/gitlab/embedded/ssl/certs/'
}
注意:GitLabを/opt/gitlab/ 以外のパスにインストールした場合は、上記のエントリーをあなたのオペレーション環境の正しいパスに修正してください。

証明書による再構成の失敗

ERROR: Not a certificate: /opt/gitlab/embedded/ssl/certs/FILE. Move it from /opt/gitlab/embedded/ssl/certs to a different location and reconfigure again.

/opt/gitlab/embedded/ssl/certs をチェックし、有効な X.509 証明書でないREADME.md 以外のファイルを削除します。

gitlab-ctl reconfigure 、カスタム公開証明書のサブジェクト・ハッシュから命名されたシンボリックリンクを構築し、 に配置します。/opt/gitlab/embedded/ssl/certs/ cacert.pem と 以外のファイルは、 に移動しますREADME.md /etc/gitlab/trusted-certs/

カスタム証明書の欠落またはスキップ

GitLab バージョン 8.9.0, 8.9.1および 8.9.2はすべて誤って/etc/gitlab/ssl/trusted-certs/ ディレクトリを使用していました。 このディレクトリが空であれば削除しても問題ありません。 まだカスタム証明書が含まれている場合は、/etc/gitlab/trusted-certs/に移動して、gitlab-ctl reconfigureを実行してください。

/opt/gitlab/embedded/ssl/certs/ にシンボリックリンクが作成されず、gitlab-ctl reconfigureを実行した後に “Skippingcert.pem” というメッセージが表示された場合、4つのイシューのうちの1つが考えられます:

  1. /etc/gitlab/trusted-certs/ のファイルはシンボリックリンクです。
  2. ファイルが有効な PEM または DER エンコード証明書ではありません。
  3. c_rehashが証明書を正しくシンボリックリンクするために必要なPerlがオペレーション・システムにインストールされていません。
  4. 証明書には文字列TRUSTED

以下のコマンドを使用して、証明書の有効性をテストします:

/opt/gitlab/embedded/bin/openssl x509 -in /etc/gitlab/trusted-certs/example.pem -text -noout
/opt/gitlab/embedded/bin/openssl x509 -inform DER -in /etc/gitlab/trusted-certs/example.der -text -noout

無効な証明書ファイルは次のように出力されます:

unable to load certificate
140663131141784:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: TRUSTED CERTIFICATE

Perl インタプリタがないためにc_rehash が証明書をシンボリックリンクしていないかどうかをテストします:

$ /opt/gitlab/embedded/bin/c_rehash /etc/gitlab/trusted-certs
bash: /opt/gitlab/embedded/bin/c_rehash: /usr/bin/perl: bad interpreter: No such file or directory

このメッセージが表示された場合は、ディストリビューションのパッケージマネージャでperlをインストールする必要があります。

証明書自体を検査する場合は、文字列TRUSTEDを探します:

-----BEGIN TRUSTED CERTIFICATE-----
...
-----END TRUSTED CERTIFICATE-----

上記の例のようになる場合は、文字列TRUSTED を削除して、gitlab-ctl reconfigure を再度実行してみてください。

カスタム証明書が検出されない

gitlab-ctl reconfigureを実行した後であれば:

  1. /opt/gitlab/embedded/ssl/certs/ではシンボリックリンクは作成されません;
  2. カスタム証明書を/etc/gitlab/trusted-certs/に配置した場合。
  3. スキップまたはシンボリックリンクされたカスタム証明書のメッセージは表示されません。

Omnibus GitLabがカスタム証明書がすでに追加されていると勘違いするイシューが発生している可能性があります。

解決するには、信頼済み証明書ディレクトリのハッシュを削除します:

rm /var/opt/gitlab/trusted-certs-directory-hash

その後、gitlab-ctl reconfigure を再度実行してください。reconfigure はカスタム証明書を検出し、シンボリックリンクするはずです。

作成者不明のLet’s Encrypt証明書

Let’s Encryptインテグレーションの初期実装では、証明書チェーン全体ではなく、証明書のみを使用していました。

10.5.4から、完全な証明書チェーンが使用されるようになりました。 すでに証明書を使用しているインストールでは、更新ロジックが証明書の有効期限が近いことを示すまで、切り替えは行われません。 切り替えを早めるには、以下を実行してください。

rm /etc/gitlab/ssl/HOSTNAME*
gitlab-ctl reconfigure

HOSTNAME は証明書のホスト名です。

Let’s Encryptの再設定に失敗しました。

再設定を行う際、Let’s Encryptが失敗する可能性のある一般的なシナリオがあります:

  1. サーバーがLet’s Encrypt検証サーバーに到達できない場合、またはその逆の場合、Let’s Encryptが失敗することがあります:

    letsencrypt_certificate[gitlab.domain.com] (letsencrypt::http_authorization line 3) had an error: RuntimeError: acme_certificate[staging]  (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 20) had an error: RuntimeError: [gitlab.domain.com] Validation failed for domain gitlab.domain.com
    

    Let’s EncryptによってGitLabの再設定にイシューが発生した場合は、ポート80と443を開いてアクセスできるようにしてください。

  2. あなたのドメインの認証局認可(CAA) レコードは、Let’s Encryptがあなたのドメインの証明書を発行することを許可していません。 再設定の出力で次のエラーを探します:

    letsencrypt_certificate[gitlab.domain.net] (letsencrypt::http_authorization line 5) had an error: RuntimeError: acme_certificate[staging]   (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 25) had an error: RuntimeError: ruby_block[create certificate for gitlab.domain.net] (/opt/gitlab/embedded/cookbooks/cache/cookbooks/acme/resources/certificate.rb line 108) had an error: RuntimeError: [gitlab.domain.com] Validation failed, unable to request certificate
    
  3. gitlab.example.comのようなテストドメインを証明書なしで使用している場合、上記のunable to request certificate エラーが表示されます。その場合、/etc/gitlab/gitlab.rbletsencrypt['enable'] = false を設定し、Let’s Encrypt を無効にします。

Let’s Debug診断ツールを使用してドメインをテストできます。 Let’s Encrypt 証明書をイシューできない原因を突き止めるのに役立ちます。

その他のトラブルシューティング

その他のトラブルシューティング手順については、「SSLのトラブルシューティング」を参照してください。

GitLabとSSLの仕組みの詳細

GitLab-OmnibusにはOpenSSLの独自のライブラリが含まれており、コンパイルされたすべてのプログラム(Ruby、PostgreSQLなど)はこのライブラリに対してリンクされています。 このライブラリは、/opt/gitlab/embedded/ssl/certsで証明書を探すようにコンパイルされています。

GitLab-Omnibusでは、/etc/gitlab/trusted-certs/ に追加された証明書をc_rehashツールを使って/opt/gitlab/embedded/ssl/certsにシンボリックリンクすることで、カスタム証明書を管理しています。例えば、customcacert.pem/etc/gitlab/trusted-certs/に追加するとします:

$ sudo ls -al /opt/gitlab/embedded/ssl/certs
total 272
drwxr-xr-x 2 root root   4096 Jul 12 04:19 .
drwxr-xr-x 4 root root   4096 Jul  6 04:00 ..
lrwxrwxrwx 1 root root     42 Jul 12 04:19 7f279c95.0 -> /etc/gitlab/trusted-certs/customcacert.pem
-rw-r--r-- 1 root root 263781 Jul  5 17:52 cacert.pem
-rw-r--r-- 1 root root    147 Feb  6 20:48 README

証明書のフィンガープリントは7f279c95で、カスタム証明書にリンクしていることがわかります。

HTTPS リクエストを行うと何が起こるのでしょうか? 簡単な Ruby プログラムを見てみましょう:

#!/opt/gitlab/embedded/bin/ruby
require 'openssl'
require 'net/http'

Net::HTTP.get(URI('https://www.google.com'))

これが舞台裏で起きていることです:

  1. requireopenssl” の行は、インタープリターに/opt/gitlab/embedded/lib/ruby/2.3.0/x86_64-linux/openssl.soをロードさせます。
  2. 次に、Net::HTTP の呼び出しは、/opt/gitlab/embedded/ssl/certs/cacert.pemのデフォルト証明書バンドル の読み込みを試みます。
  3. SSLネゴシエーションが行われます。
  4. サーバーはSSL証明書を送信します。
  5. 送信された証明書がバンドルでカバーされていれば、SSLは正常に終了します。
  6. そうでない場合、OpenSSL は、事前に定義された証明書ディレクトリの内部で、そのフィンガープリントに一致するファイルを検索することで、他の証明書を検証する可能性があります。例えば、証明書がフィンガープリント7f279c95を持つ場合、OpenSSL は/opt/gitlab/embedded/ssl/certs/7f279c95.0を読み込もうとします。

OpenSSLライブラリは、SSL_CERT_FILESSL_CERT_DIR 環境変数の定義をサポートしていることに注意してください。 前者はロードするデフォルトの証明書バンドルを定義し、後者はより多くの証明書を検索するディレクトリを定義します。trusted-certs ディレクトリに証明書を追加している場合は、これらの変数は必要ありません。 しかし、何らかの理由で設定する必要がある場合は、環境変数として定義することができます。 たとえば、次のようにします:

gitlab_rails['env'] = {"SSL_CERT_FILE" => "/usr/lib/ssl/private/customcacert.pem"}