Cloudflare Tunnelを使うと、アウトバウント接続のみでプライベートのサーバを公開することができて、とても便利です。
そのままの状態でもWAFでのチェックもしてもらえるのですが(無料で!)、さらにCloudflare側で認証を追加することもできます(無料で!!)。そうすると認証を通ってないアクセスがトンネル内に入ってこないので、非常に安心です。
しかしながら、Grafanaのように標準で認証が有効になっているサーバを使うと、連続で2回認証をする必要があり、さすがに不便です。そこでCloudflareで認証したらそのままSSOでログインできる方法を見つけたので紹介します。
システム構成概要とシーケンスイメージ
システム要件
本項では以下のシステム要件が必要です。
- cloudflaredと公開用サーバがInternetアクセスできること
- 公開用サーバがJWT認証に対応していること1
ポイントとキーワード
Cloudflareで認証をすると、トークンとしてJWTを付与した形で、サーバにリクエストを転送することができます。受け取ったサーバがJWTを使って認証することができればSSOログインが実現できます。
JWTを使って認証するときには改ざんやなりすましされていないかを検証するのがセキュアです2。そこでサーバはJWT検証用の公開鍵を提供するJWKS(JSON Web Key Set)エンドポイントにアクセスして、公開鍵を入手し、JWTの検証をします3。
JWKS接続時は、cloudflaredを経由しないので、普通のInternetアクセス(アウトバウンド)が必要です4。
設定手順
今回は下記の設定が必要になります。
- Cloudflare Tunnel:
- Tunnelの追加
- Access Groupの追加
- Applicationの追加
- Grafana:
- grafana.iniの設定
- ログイン用ユーザーの追加
今回は既存のTunnelに新しいURLを追加します。Tunnelの新規作成とは異なりますが、Access GroupやApplicationの設定は同様です。
Cloudflare Tunnelの追加
Cloudflareの管理画面でZero Trust
> Access
> Tunnels
と選択すると編集画面が出るので既存のトンネル名をクリックします。
トンネルの情報画面が出るので、Configure
をクリックして編集画面に入ります。
Add a public hostname
でサーバ用URLの追加画面に入ります。
今回は既存のドメインに Subdomain
を追加します。このURLで転送するGrafanaのURLとポートも併せて指定します。
URLと転送先の設定はこれで完了です。
Access groupsの設定
認証を使うのが初めての場合、ログインを許可するユーザーの登録を行います。
Zero Trust
> Access
> Access Groups
で画面に入り Add a group
をクリックします。
Group name
は任意です。今回はメールアドレス宛にOne-time PINを発行する方法にするので、グループの定義情報として Selector
にEmailを選択し、 Value
に認証したいメールアドレスを入力します。
なお、認証に使えるユーザー数はプランによって上限があり、フリープランでは50名です(すごい!)。
画面に従って保存すればOKです。
Applicationの追加
最後に認証する対象のURL、ログインを許可するAccess Groupなどを1つのアプリケーションとして設定します。
Zero Trust
> Access
> Application
で画面に入り Self-hosted
を選択します
Application name
は任意ですが、この後Cloudflareで認証する画面に表示されるので、どこにログインしようとしている画面か直感的にわかる名前にするとよいと思います。
Subdomain
と Domain
は今回はTunnelで設定したものと同様にします。
また同じ画面でどの認証方法を使うかも設定できます。今回はOne-time PINが自動的に選ばれています。
Policy name
は任意です。Assign a groupにログインさせたいユーザーを登録したグループが選択されていることを確認します。
画面に沿って Add application
を押して完了です。
この時点で、URLにアクセスすると、Cloudflare Accessの認証画面が表示されるようになります。
Grafana.iniの設定
Cloudflare Accessの認証結果を使ってJWT認証をするためにgrafana.iniは下記のように設定が必要です。
########## Users ##########
[users]
allow_sign_up = false
auto_assign_org = true
########## Auth JWT ##########
[auth.jwt]
enabled = true
header_name = Cf-Access-Jwt-Assertion
email_claim = email
username_claim = email
jwk_set_url = https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/certs
# for extra verification, set to "Application Audience (AUD) Tag"
# which can be found in the app you create in Cloudflare Access
expect_claims = {"aud":"<Application Audience (AUD) Tag>"}
auto_sign_up = true
jwk_set_urlで指定する<your-team-name>はZero Trust
> Settings
> Custom Pages
で確認することができます。
また<Application Audience (AUD) Tag>は先ほど設定したApplication
ページの設定画面に再度入ると、Overview
タブのApplication domain
の下に表示されています。
今回はDockerでGrafanaを上げているので、環境変数 GF_PATHS_CONFIG
を変更し、作成したgrafana.iniを読み込ませます。
Grafanaユーザー作成
JWT認証すると自動的にユーザーが作成されるはずですが、今回は管理者権限を付与したかったので、あらかじめGrafanaでユーザーを作成し、権限を付与しておきました。
この時Name、Email、UsernameはすべてJWTで渡されるメールアドレスと同じにしておきます。
動作確認
Application
で設定したURLにアクセスすると下記画面が出てきます。
Emailに認証したいメールアドレスを入れるとPINコードが送られてくるので、下記画面にPINコードを入力します。
Grafanaに自動ログインすることができます。
お疲れさまでした。