やったことのまとめ
Prometheus
はデフォルトだとHTTP
(暗号化なし)で公開されるが, セキュリティの観点からどうしてもHTTPS
で動かしたい場合がある.
今回はnginx
を使ってリバースプロキシする方法とPrometheus
自体をHTTPS
化する方法の2通りの方法を試してみた.
つかうもの
- macOS Mojave 10.14
Docker
のホストとして使用, 動作確認用のブラウザもこちらで起動する
- Google Chrome
- バージョン: 88.0.4324.150(Official Build) (x86_64)
- Docker Desktop for Mac
- Version 3.1.0
- Docker Engine Version 20.10.2
- docker-compose version 1.27.4
- Prometheus (Docker)
- version 2.24.1
- nginx (Docker)
- version 1.18.0
- openssl
- version 1.1.1d
やったこと
秘密鍵とオレオレ証明書の作成
まずはHTTPS
で通信を行うためにopenssl
で秘密鍵とSSL証明書(オレオレ証明書)を作成する.
(公的な証明書と鍵のペアがある場合は不要. 文中のhogehoge.comは適切なホスト名に置き換える.)
オレオレ証明書を作るときは以前のやり方に加えて,
ページをChrome
で開いた場合も怒られないようにSANs(Subject Alternative Names)
を設定するようにする.
今回の鍵と証明書の作成に使用するopenssl
はnginx
のDocker image
に入っているものを使う.
# nginxコンテナの中で実行(カレントディレクトリをマウントしておく)
$ docker container run --rm -it -v="$PWD:/workdir" -w="/workdir" --entrypoint=/bin/bash nginx:1.18.0
## ここからコンテナ内
$ openssl version
OpenSSL 1.1.1d 10 Sep 2019
# 秘密鍵(private-key.pem)の作成
$ openssl genpkey -algorithm RSA -out private-key.pem
# オレオレ証明書(cert.pem)の作成(CSRの作成と署名)
# SANsの設定もやっておく(Chrome対応)
$ openssl req -x509 -key private-key.pem -out cert.pem -addext 'subjectAltName = DNS:hogehoge.com,DNS:fugafuga.com'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:hogehoge.com
Email Address []:
# 証明書の中身を確認(SANsが追加されている)
$ openssl x509 -in cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
24:4c:ec:40:cc:94:5c:a2:af:30:6a:e9:7d:5c:17:28:5e:fb:ec:fc
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = hogehoge.com
Validity
Not Before: Feb 10 16:13:01 2021 GMT
Not After : Mar 12 16:13:01 2021 GMT
Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = hogehoge.com
...
X509v3 extensions:
...
X509v3 Subject Alternative Name:
DNS:hogehoge.com, DNS:fugafuga.com
# コンテナから出る
$ exit
## ここからホストOS(Mac)
# 秘密鍵と証明書ができている
$ ls
cert.pem
private-key.pem
次にSANs
に指定したhogehoge.comでlocalhost(127.0.0.1)にアクセスできるよう,Mac
(Prometheus
を起動するマシン)の名前解決設定(/etc/hosts
)を編集する.
# /etc/hostsにhogehoge.com(localhost)を追加
$ echo "127.0.0.1 hogehoge.com" | sudo tee -a /etc/hosts
最後に今回作った証明書(cert.pem
)は公的な認証局が署名したものではないので,
証明書をMac
のキーチェーンアクセス
で開いて常に信頼するよう設定する.
これでHTTPS
化に必要な証明書の設定は完了.
nginxを挟んでHTTPS化する
次に公式の手順1に従ってnginx
をHTTPS
化して, その後ろでPrometheus
が動く構成(リバースプロキシ)をつくる.
今回も例に依ってDocker Compose
で試すが, 非コンテナ環境の場合はコンテナ名で名前解決している部分を適切な名前(ホスト名)に置き換えて,docker-compose.yml
で指定している場所に各種の設定ファイルを配置すれば動くはず.
Prometheus
- リバースプロキシ用の設定を引数で設定
--web.external-url
: 証明書のSANs
に指定した名前+リクエストを受け付けるパス--web.route-prefix
:/
を明示的に指定
- リバースプロキシ用の設定を引数で設定
nginx
Prometheus
のリバースプロキシとHTTPSの設定をhttps.conf
に記述する- 秘密鍵, 証明書を指定の場所に配置する
コンテナを立ち上げてみる.
# cert.pemとprivate-key.pemは先ほど作ったオレオレ証明書と秘密鍵
$ tree .
.
├── cert.pem
├── docker-compose.yml
├── https.conf
└── private-key.pem
# コンテナ起動
$ docker-compose up -d --force-recreate --remove-orphans
# localhostの443ポートがnginxコンテナに割り当てられている
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:443->443/tcp, 80/tcp
prometheus /bin/prometheus --config.f ... Up 9090/tcp
# オレオレ証明書(cert.pem)を信頼する設定でPrometheus APIを叩いてみる
$ curl --cacert ./cert.pem https://hogehoge.com/prometheus/api/v1/label/job/values
{"status":"success","data":["prometheus"]}
コンテナが立ち上がり, hogehoge.comがHTTPS
で公開されていることが確認できた.
念の為Chrome
でhttps://hogehoge.com/prometheus/を開いてみる.
Prometheus
がHTTPS
で公開されていて, Chrome
がオレオレ証明書を信頼していることが確認できた.
Prometheus単独でHTTPS化する
今までPrometheus
をHTTPS
化する際は先ほど試したようにリバースプロキシを使うのが推奨されていたのだが,
なんとversion 2.24からはPrometheus
単独でのHTTPS
化にも対応した2らしい(まだお試し機能らしいが)ので試してみる.
まずは新しいHTTPS
関連の設定ファイルweb-config.yml
3で証明書と秘密鍵の場所を指定する.
(この他にもクライアント認証やBasic認証も設定できるらしい.)
次にPrometheus
の実行時引数--web.config.file
でweb-config.yml
の場所を指定する.
また, hogehoge.comでアクセスを受けられるように--web.external-url
を設定する(nginx
を使う場合と異なり/prometheus
は不要).
コンテナを立ち上げてみる.
# cert.pemとprivate-key.pemは先ほど作ったオレオレ証明書と秘密鍵
$ tree .
.
├── cert.pem
├── docker-compose.yml
├── private-key.pem
└── web-config.yml
# コンテナ起動
$ docker-compose up -d --force-recreate --remove-orphans
# localhostの443ポートがPrometheusコンテナに割り当てられている
$ docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------
prometheus /bin/prometheus --config.f ... Up 0.0.0.0:443->443/tcp, 9090/tcp
# オレオレ証明書(cert.pem)を信頼する設定でPrometheus APIを叩いてみる
$ curl --cacert ./cert.pem https://hogehoge.com/api/v1/label/job/values
{"status":"success","data":["prometheus"]}
次にChrome
でhttps://hogehoge.com/を開くと, nginx
を使ったときと同様にPrometheus
がHTTPS
で公開されていることがわかる.
やったぜ.
ただしnginx
を使う場合には無かった注意点として, 今回はPrometheus
自身がHTTPS
で起動しているため,
自身のメトリクス(/metrics
)のスクレイプ設定がデフォルトのままだとプロトコルがHTTP
のままなのでスクレイプに失敗する.
今回はとりあえずPrometheus
をHTTPS
化するのが目的だったので, ここでおわり.
おわり
Prometheus
をHTTPS
化してみた.nginx
を使う方法はそれはそう…という感じだけど, Prometheus
単体でHTTPS
化できるのは知らなかった.
ただしPrometheus
単独でのHTTPS
対応はまだお試し機能っぽいのと,Alertmanager
はまだ対応してない?みたいなので, 併せて対応する場合はnginx
を使うように統一したほうが良さそう.