SSL 証明書管理

KE 2.0 システムでは HTTPS 接続および AMQPS 接続を行なうために、SSL 証明書が必要になります。 ke2-docker パッケージのデプロイ手順では、自己署名 SSL 証明書を作成しています。

注意: 自己署名 SSL 証明書を適用することで暗号化通信には対応していますが、セキュリティ上のリスクがあることは理解しておいてください。特に外部からのアクセスを許可するようなシステム構成の場合には、正式な SSL 証明書の発行と適用を検討してください。

SSL 証明書ファイルの作成

ke2-docker パッケージに付属の create-cert.sh スクリプトを実行すると、自己署名 SSL 証明書を作成します。

$ ../../../scripts/create-cert.sh

ssl ディレクトリに以下のファイルが生成されます。

ファイル名説明
local-ca.crt作成する SSL 証明書に署名する CA 証明書
local-ca.keylocal-ca.crt の秘密鍵ファイル
local-ca.srllocal-ca.crt で発行済みシリアル番号を保存するファイル
server.crtnginx/rabbitmq コンテナが利用するサーバ SSL 証明書(local-ca.crt によって署名されています)
server.csrserver.crt を生成する時の CSR ファイル
server.extserver.crt に設定する拡張情報ファイル
server.keyserver.crt の秘密鍵ファイル
  • create-cert.sh は rabbitmq コンテナに含まれる openssl コマンドを利用して、自己署名 SSL 証明書を作成しています。
  • create-cert.sh で作成される CA 証明書および SSL 証明書の、秘密鍵種別は RSA (2048bit)、有効期間は 3650 日です。
  • サーバ証明書 server.crt の Common Name (CN) および Subject Alternative Names (SANs) には、create-cert.sh スクリプトを実行したホストの hostname コマンドで取得したホスト名が設定されます。

各コンテナでの SSL 証明書の適用

ke2-docker でデプロイした各コンテナについては、create-cert.sh スクリプトで作成した SSL 証明書 (server.crt) を適用するように設定を行なっています。 各コンテナでの設定内容は以下のようになっています。

nginx コンテナ

nginx コンテナでは、SSL 証明書を利用した HTTPS 接続ができるように、以下のような設定を行なっています。

  • SSL証明書ファイル一式を nginx コンテナの /etc/nginx/ssl ディレクトリにバインドするようにしています。
  • /etc/nginx/ssl に配置された SSL 証明書を利用するように、ke2-docker 付属の nginx.conf で設定しています。

rabbitmq コンテナ

rabbitmq コンテナでは、SSL 証明書を利用した AMQPS 接続ができるように、以下のような設定を行なっています。

  • 起動時に、SSL証明書ファイル一式を rabbitmq コンテナの /etc/rabbitmq/ssl ディレクトリにコピーするようにしています。
  • /etc/rabbitmq/ssl に配置された SSL 証明書と CA 証明書を利用するように、ke2-docker 付属の rabbitmq-ssl.conf で設定しています。
  • rabbitmq-server で SSL 証明書による認証ができるように rabbitmq_auth_mechanism_ssl プラグインを有効化しています。

更新した SSL 証明書の再適用

SSL 証明書ファイル (server.crt) および秘密鍵ファイル (server.key) を更新(上書き)したときは、各コンテナに更新された SSL 証明書を改めて適用する必要があります。

注意: クラスタ構成の場合は、この再適用の手順をすべてのノードで実施してください。

もっとも簡単な方法としてはコンテナの再起動になります。 これはコンテナが起動するたびに、上記の「各コンテナでの SSL 証明書の適用」が更新された SSL 証明書を対象に同様に適用されることを意味しています。

一方で、コンテナを再起動せずに、更新された SSL 証明書を適用させたいという場合もあります。 その場合は、動作中のコンテナごとに SSL 証明書をリロードさせる必要があります。

ke2-docker パッケージに付属の reload-cert.sh スクリプトを実行すると、動作中の各コンテナに対して SSL 証明書のリロードを指示します。 これにより更新された SSL 証明書を適用させることが出来ることになります。

$ ../../../scripts/reload-cert.sh

リロードを指示したあとに、ブラウザでアクセスして SSL 証明書が更新されていることを確認してください(例えば有効期限が伸びているはずです)。

reload-cert.sh スクリプトは 2.0.3.post1 以降で対応しています。

この reload-cert.sh スクリプトが各コンテナごと実施している適用手順について、以下に説明します(reload-cert.sh を利用する場合は、個別の適用手順を実施する必要はありません)。

nginx コンテナ

nginx コンテナに対しては、以下の手順で更新された SSL 証明書を適用することができます。

  • nginx コマンドで reload を指示する。

ホスト上で実行するコマンドとしては以下のようになります。

$ docker exec -it $(docker ps -q -f name=nginx) nginx -s reload

rabbitmq コンテナ

rabbitmq コンテナに対しては、以下の手順で更新された SSL 証明書を適用することができます。

  • 更新された SSL 証明書を rabbitmq-server/erlang がアクセスできる場所にコピーする。
  • erlang が保持している SSL 証明書キャッシュをクリアする。

ホスト上で実行するコマンドとしては以下のようになります。

$ docker exec -it $(docker ps -q -f name=rabbitmq) sh -c "/bin/cp -f -a -r -T /run/.kompira_ssl /etc/rabbitmq/ssl && chown -R rabbitmq:rabbitmq /etc/rabbitmq/ssl"
$ docker exec -it $(docker ps -q -f name=rabbitmq) rabbitmqctl eval "ssl:clear_pem_cache()."

正式な SSL 証明書の適用

各コンテナでの SSL 証明書の適用」で示したとおり、各コンテナはホストの ssl ディレクトリにある SSL 証明書ファイルを利用するように設定されています。 ke2-docker パッケージのデプロイ手順では自己署名 SSL 証明書を作成していますが、 外部より正式に発行された SSL 証明書ファイルと秘密鍵ファイルを同じ場所に配置してからコンテナを起動すれば、 正式な SSL 証明書を各コンテナに適用できることにもなります。

このとき、正式な SSL 証明書ファイルと秘密鍵ファイルを、ssl ディレクトリに以下のとおり同じ名前で配置する必要があることには注意してください。

ファイル名説明
server.crtnginx/rabbitmq コンテナが利用する正式に発行された SSL 証明書
server.key正式に発行された server.crt の秘密鍵ファイル

正式な SSL 証明書を発行する手続き等については、ご利用になる SSL 証明書発行ベンダーにお問い合わせください。

一例として、無料で利用できる Let's Encrypt による SSL 証明書の発行と適用については、その手順を「Let's Encrypt による SSL 証明書の発行と適用」で紹介します。

独自 CA 証明書の適用

ユーザーの環境によっては、独自の認証局 (CA) によって発行された自己署名 SSL 証明書が適用されたサーバーが運用されていて、コンテナからそのようなサーバーへ HTTPS 接続を行いたいというニーズがあるかもしれません。例えば、ジョブフローで urlopen() を用いてそうしたサーバに (verify=trueで) HTTPS アクセスさせたい、または、自己署名 SSL 証明書で HTTPS 運用しているリポジトリサーバに対してリポジトリオブジェクトを用いて連携したい、などが考えられます。

ですが、自己署名 SSL 証明書で運用しているサーバへの HTTPS アクセス時には、SSL 証明書の検証エラーが起きることが想定されます。 これはセキュリティ上当然の挙動であり、意図されたものです。

その対策としては、各コンテナに独自 CA 証明書を適用しておくことで、その CA で発行された SSL 証明書が適用されたサーバへの HTTPS アクセスにおいて、証明書の検証が正常にパスするようにすることができます。

注意: ただし、一般的にはセキュリティ強度を下げる行為(例えば中間者攻撃のリスクなどが高まる)と捉えられるため、各ユーザ組織におけるセキュリティポリシーと照らし合わせて、リスクを十分に評価し、慎重に検討してください。

その上で、各コンテナに独自 CA 証明書を適用する方法については、以下で説明します。

独自 CA 証明書ファイルの適用手順

SSL 証明書ファイルの作成」で説明したように、ke2-docker パッケージに付属の create-cert.sh スクリプトを実行すると、ssl ディレクトリに以下のファイルが生成されます。この ssl ディレクトリ内にさらに ca-certificates というディレクトリを作成し、そこに適用したい CA 証明書ファイルを配置してください。このとき CA 証明書ファイルの拡張子は .crt としてください。

  • ssl/ca-certificates
  • ssl/ca-certificates/*.crt

このように CA 証明書ファイルを配置したうえでコンテナを起動すると、コンテナ内部でここに配置した CA 証明書ファイルを自動的に信頼ストアに取り込みます。

この「独自 CA 証明書ファイルの適用手順」は 2.0.3.post1 以降で対応しています。

注意: この手順はコンテナ起動時の適用にしか対応していません。独自CA証明書を更新した場合はコンテナを再起動してください。

コンテナ起動時の信頼ストアの自動更新

コンテナ起動時の CA 証明書ファイルの信頼ストアへの取り込みは、具体的には内部で以下のような処理を行なっています(ユーザが実行する必要はありません)。

  • ホスト上の ssl/ca-certificates/*.crt に配置された CA 証明書ファイルを、コンテナ内のローカル CA 証明書ディレクトリ /usr/local/share/ca-certificates/ にコピーします。
  • update-ca-certificates コマンドを実行して、証明書を信頼ストアに追加します。

update-ca-certificates コマンドによって、すべての CA 証明書がマージされた /etc/ssl/certs/ca-certificates.crt というファイルが更新されます。 HTTPS 接続を行なう場面でこの ca-certificates.crt を CA 証明書として利用すれば、追加した独自 CA 証明書によって発行された SSL 証明書を持つサーバへの HTTPS 接続において、証明書の検証がパスすることになります。

先述したジョブフローの urlopen() やリポジトリサーバの連携における HTTPS アクセスでは、内部的に Python の requests モジュールが利用されています。 requests モジュールは環境変数 REQUESTS_CA_BUNDLE で CA 証明書を指定することができるようになっています(参考)。

kompira, kengine, jobmngrd コンテナでは、環境変数 REQUESTS_CA_BUNDLE をデフォルトで /etc/ssl/certs/ca-certificates.crt と設定するようにしています。 これによりこれらのコンテナにおける requests モジュールによる HTTPS アクセスにおいて、独自 CA 証明書ファイルが適用できるようになっています。