SSL 自己署名証明書と Docker レシピ その1
今年も AdventCalendar の季節ですね ㊗ 日立グループ からも元気に参加します!
OSSソリューションセンタ 神山 が先陣を切らせて頂きたく。
とある社内インフラ屋の困りごと
私はとある社内システムの設計、構築、運用、etc …ゆりかごから墓場まで面倒を見ています。
最近はコンテナが大好物です。
そんな私をたまに苦しめるのが、会社やチーム内独自の 自己署名証明書 (self-signed certificate、通称 オレオレ証明書) という存在です。理想を言えば、然るべき認証局に署名してもらうべきです。
しかし、イントラネットや開発中の環境だと、どうしてもそれが難しいことがあります。
特に Docker や Kubernetes を使い始めると、この”オレオレ証明書”の扱いが非常に面倒になっています (新しいイメージ使おうと思うとすぐに証明書エラー…)。巷では、「sslVerify = false」みたいな設定がはびこるわけですがセキュリティ上リスクが大きいです。
そこで今回は、(Docker) コンテナ利用を前提に、オレオレ証明書をうまく扱うための方法を書き並べてみました。
コンテナでオレオレ証明書を使う
コンテナでオレオレ証明書を正しく使う方法ですが…
- イメージビルド時に証明書もインストールする
- 実行時に証明書をマウントする
このような方法があるかと思います。今回は、それぞれ見ていきます。
イメージビルド時に証明書もインストールする
いくつかのOSについて、ビルド時に 証明書を入れていきます。
Dockerfile
self-signed.cert
上記のようなファイル構成を想定しています。
self-signed.cert がオレオレ認証局のCA証明書です。 PEM形式を想定しています。DER系式など、異なる形式の場合は事前に変換が必要です(参考)。このファイルをコンテナ内に登録し、コンテナ内部でこの証明書を”信用できる”証明書として登録していきます。
今回はそれぞれベースイメージや公式イメージを元にしました。
執筆時点(2020年11月)で安定版のタグを利用しています。
Ubuntu (Debian)
FROM ubuntu:20.04
COPY self-signed.cert /usr/local/share/ca-certificates/extra/self-signed.crt
RUN apt-get update -y && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* && update-ca-certificates
執筆時点のca-certificates
は、20201027ubuntu0.20.04.1
でした。
- 所定の場所(/usr/local/share/ca-certificates/extra/)に証明書を配置
- ca-certificates パッケージをインストール
- update-ca-certificates を実行
これで完了です。上記の例では、ごみファイルを残さないように、ということで最後 /var/lib/apt/lists 以下を削除しています。
debian(debian:10) でも同様の手順となります。
Alpine Linux
FROM alpine:3.12
COPY self-signed.cert /usr/local/share/ca-certificates/self-signed.cert
RUN apk add --no-cache ca-certificates && update-ca-certificates
執筆時点のca-certificates
は、ca-certificates-20191127-r4
でした。シンプルに、
- 所定の場所(/usr/local/share/ca-certificates/)に証明書を配置
- ca-certificates パッケージをインストール
- update-ca-certificates を実行
でOKです。
CentOS
FROM centos:7
COPY self-signed.cert /usr/share/pki/ca-trust-source/anchors/self-signed.crt
RUN yum install -y ca-certificates && update-ca-trust && yum clean all
centos:latest (執筆時点では centos:8 )は、dnfコマンドがうまく動かなかったので、妥協して centos:7 としました。執筆時点のca-certificates
は、ca-certificates-2020.2.41-70.0.el7_8.noarch
でした。
こちらも、
- 所定の場所(/usr/share/pki/ca-trust-source/anchors/)に証明書を配置
- ca-certificates パッケージをインストール
- update-ca-trust を実行
でOKです。
Java
FROM openjdk:15
COPY self-signed.cert /tmp/self-signed.cert
RUN keytool -import -trustcacerts \
-file /tmp/self-signed.cert \
-noprompt -storepass changeit \
-cacerts \
-alias self-signed
執筆時点では OpenJDK:15 (openjdk version "15.0.1" 2020-10-20) でした。
基本的な流れは
- 適当な場所に証明書を配置
-
keytool コマンドで取り込み
- それぞれのオプションの説明はほかに譲ります
- OpenJDK14 あたりから、-keystore で cacerts キーストアの場所を指定するのは warning 扱いになりました。 -cacerts だけで済むのでこちらの方が楽ですね
- -alias オプションでわかりやすい名前を付けると良いです
処理によってはOS側の証明書を参照してくれますが、過去に Java VM 側でも証明書を覚えておかないとうまく動かないことがあったので載せてみました。
実行時に証明書をマウントする
イメージを自前でビルドするとバージョン管理が面倒になることがあります。そういう場合は、実行時にマウントするという手があります。ここは Debian/Ubuntu の場合について書きます。
Debian/Ubuntu
まずは、update-ca-certificates コマンドの結果出力されるファイルを保存します。本記事のイメージビルド時に証明書をインストールする方法でイメージ をビルド(ここではイメージ名を certs )します。
そして、
docker build -t certs .
docker create --name certs certs
docker cp certs:/etc/ssl/certs/ca-certificates.crt certs.crt
docker rm certs
コンテナからファイルを取り出します。既に動作させてるUbuntu環境からファイルをコピーしても良いのですが、上記のように極力クリーンな環境からコピーしたほうが間違いが少ないです。こうすることで、後々Ubuntuのバージョンがあがり、ca-certificates.crt
の形式が変わった場合も、同じ手順で更新できます。
ここまで出来たら、後は
docker run -v `pwd`/certs.crt:/etc/ssl/certs/ca-certificates.crt -it ubuntu bash
このように、同ディレクトリにマウントしてコンテナを起動することで、オレオレ証明書を認識した状態でコンテナを立ち上げることができます。上記では Ubuntu を起動していますが、Ubuntuベースのイメージであれば、同じパスにマウントすることで、期待通りに動作します。
さいごに
今回は、OSのベースイメージ毎に、SSL証明書の登録の仕方をまとめてみました。
実際は、JenkinsやRedmineなどのイメージに対して証明書を埋め込みたいケースもあるかと思います。そういったケースにどう対応するか…は その2 として公開したいと思います。