Featured image of post クライアント認証のかかったPrometheusにGrafanaでアクセスする

クライアント認証のかかったPrometheusにGrafanaでアクセスする

みんなに証明書を配るのが面倒

やったことのまとめ

クライアント認証がかかったPrometheusGrafanaでアクセスした.

Prometheusへの認証に必要な情報(証明書と秘密鍵)をGrafanaに持たせることができるので,
Grafanaへアクセスする権限さえあればクライアント認証のかかったPrometheusのメトリクスが閲覧できるようになる.

つかうもの

やったこと

クライアント認証をかけたPrometheusの準備

Prometheusにクライアント認証をかけるで用意したものを使う.
秘密鍵や証明書もそのまま同じもの.
(ただしGrafanaにはクライアント認証をかけないのでMacに証明書を読み込ませる必要はなし)

今回はnginxを挟んで使う方法を採用するが, Prometheus単独でクライアント認証をかけた場合でもGrafanaの設定は同じはず.

Grafanaでクライアント認証を突破する

GrafanaはDataSource(Prometheus)への認証方法としてクライアント認証に対応しているので,
クライアント証明書クライアント秘密鍵(クライアントの身元を証明するのに使用),
サーバー認証局の証明書(サーバーの身元を確認するのに使用)を持たせる.

GrafanaがDataSourceへクライアント認証で接続するための設定はdatasource.yaml1に記述する.
証明書と秘密鍵をベタ書きしたくないので, File provider2を使ってファイル名を指定して指定して読み込むようにした.
(このあたりはissue3を参考にした)

apiVersion: 1
deleteDatasources:
- name: Prometheus
orgId: 1
datasources:
- name: Prometheus
isDefault: true
editable: false
type: prometheus
orgId: 1
url: https://prometheus.hogehoge.com # Prometheusのサーバー証明書のSANsに指定したホスト名
jsonData:
tlsAuth: true # クライアント認証時にクライアント証明書とクライアント秘密鍵を提示する
tlsAuthWithCACert: true # サーバー認証局の証明書を確認する(サーバー証明書が公的な認証局で署名されている場合は不要かも)
tlsSkipVerify: false # めんどくさいときはここをtrueにする(サーバー証明書の正当性を確認しなくなる)
secureJsonData:
tlsCACert: $__file{/etc/grafana/server-cert.pem} # サーバー認証局の証明書(サーバー証明書が公的な認証局で署名されている場合は不要かも)
tlsClientCert: $__file{/etc/grafana/client-cert.pem} # クライアント証明書
tlsClientKey: $__file{/etc/grafana/client-private-key.pem} # クライアント秘密鍵
view raw datasource.yaml hosted with ❤ by GitHub

各種ファイルをGrafanaのコンテナにマウントして起動する.
(今回はProemtheus+nginxの構成にしているが, Prometheus単独でクライアント認証をかけた場合でもGrafana側の設定は同じになる)

version: "3.9"
services:
prometheus:
image: prom/prometheus:v2.27.1
command: [
"--config.file=/etc/prometheus/prometheus.yml",
"--web.external-url=https://prometheus.hogehoge.com",
"--web.route-prefix=/",
]
nginx:
container_name: prometheus.hogehoge.com # コンテナから名前解決できるようにコンテナ名をサーバー証明書のSANsに指定したホスト名にする
image: nginx:1.21.0
volumes: [
"./https.conf:/etc/nginx/conf.d/https.conf",
"./server-cert.pem:/etc/nginx/https/server-cert.pem",
"./server-private-key.pem:/etc/nginx/https/server-private-key.pem",
"./client-ca-cert.pem:/etc/nginx/https/client-ca-cert.pem",
]
grafana:
image: grafana/grafana:7.5.7
volumes: [
"./datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml",
"./client-cert.pem:/etc/grafana/client-cert.pem", # クライアント証明書
"./client-private-key.pem:/etc/grafana/client-private-key.pem", # クライアント秘密鍵
"./server-cert.pem:/etc/grafana/server-cert.pem", # サーバー認証局の証明書(サーバー証明書が公的な認証局で署名されている場合は不要?)
]
ports:
- 3000:3000 # ホストOSの3000番ポートをこのコンテナの3000番に割り当てる
# ディレクトリの状態(使わないものを消している)
$ ls -1
client-ca-cert.pem
client-cert.pem
client-private-key.pem
datasource.yaml
docker-compose.yml
https.conf
server-cert.pem
server-private-key.pem

# コンテナを起動する
$ docker compose up -d --force-recreate --remove-orphans

今回Grafanaは単独で動かしている(HTTPS化もしていない)のでChromeでhttp://localhost:3000を開く.
(GrafanaはデフォルトでBasic認証がかかっているので, admin:adminで突破する)

Grafananginxのクライアント認証を突破し,
Prometheusのメトリクスを取得できることが確認できた.

# コンテナを終了しておく
$ docker compose down

おわり

Grafanaでクライアント認証のかかったPrometheusからメトリクスを習得する流れを確認した.

Prometheusのセキュリティまわりはこれで一安心な感じもするが, 要件によってはGrafanaにも別の認証をかけたほうがいいかも…

おまけ