見出し画像

Keycloakのためのリバースプロキシーを設定する

概要の掴み

Keycloakは後発の認証認可制御を実現するソフト。同種だとForgelock OpenAMが競合。
OpenAMは基本的にクローズドソース開発に移行しているので、OSSとなるとKeycloakが有力。
エージェント型だけでなく、リバースプロキシ型も実現可能。

それほどの労力をかけずに、しかし自前ではない仕組みで(認可は一旦置いておいて)認証制御の基盤を実現したい。
そう持ちかけたところ、Keycloakを紹介してもらい、検討に入った。

今回はリバースプロキシー型を採用したかった。
また、プロジェクト内ではnginxを使用していた関係で、nginxでのリバプロを実現しようと試みた。
が、結果的には時間切れとなり、httpdでのリバプロを実現に至っている。(過去に設定した例を紹介してもらい、プロジェクト用にチューニングしてことなきを得た)


まず、Keycloakのhttpdのリバプロで実現に必要な情報は下記がベース。


その他、次の記事が具体的で参考になる。

あとは、この記事がKeycloakの概要を理解するのにとても役立った。

実例と修正

次の箇所に最低限必要な設定の例が上がっている。

また、ドキュメント内にも、もう少しコード片として設定値が具体的になっているものが記載されている。

動かすにあたって手当てする必要があったのは次のエラーのみ。

Request Header Field Size Exceeds Limit for Web server

修正はそれほど難しくなくて、次の対応を入れるだけ。

LimitRequestFieldSize 65536
ProxyIOBufferSize 65536


あとは苦労したのが、リバースプロキシー設定にするにあたり、未認証時に認証用に飛ばすロケーションを、リバースプロキシー設定する箇所とは別に設ける必要があった点。例えばこんな感じ。

   <Location /my-auth>
       AuthType openid-connect
       Require valid-user
       OIDCUnAuthAction 401
   </Location>
   <Location /my-app>
       AuthType openid-connect
       Require valid-user
       ProxyPass http://my-internal-app:8080/
       ProxyPassReverse http://my-internal-app:8080/
   </Location>

/my-appにアクセスがあったら、別で設定するリダイレクト先に飛ばす。そのリダイレクト先は/my-auth/reduirect_uriとかそんな感じにする。
やりながらなれる部分なのかもしれないけれど、この辺りの設定は実例で見せてもらえていなかったら詰まっていただろうと思う。


その他のつまずき

上の話までは対応として必要だったことでそれ以外での詰まった話。2つある。固有の事情によるものだから読まずに飛ばしても本筋に影響しない。

1つ目、まずProxyPassについて。
これは変なのにハマった。エラー内容は次の通り。

ProxyPass worker name too long httpd

後方互換性の関係で、安定板に対してこの修正は入らないことが決まったよう(at 2020-07-01, 起票から実に8年越し)なのだけど、要はProxyPassから飛ばす先のURLの長さには制限があるという話。96文字とハードコードされてしまっているのだとか......。
関連するリンクをいくつか貼っておく。

最悪自前でビルドすることも考えたけれど、見た限り、一手間というレベルではなかったし、諸般の事情を考慮してもその方法は悪手に思えたので自前での修正・ビルド対応はしなかった。

で、上記96文字制限を回避する方法としては、RewriteRuleを使用することで、飛んできたアクセスを書き換えるというものがあった。
ただ、今回の場合、リバースプロキシーとして動作させたいので、例えば、次のような要解決事項がある。

* "proxy.example.com"にアクセスが来たら、"content.example.com"へアクセスさせたい。
* "proxy.example.com/mypage/profile"のようなアクセス先にアクセスしたら、"content.example.com/mypage/profile"にアクセスさせたい。

で、結果として、これを限定した時間の中では、解決する方法を見つけることはできなかった。

* 固定でcontent.example.comに飛ばすことはできた
* ところが/mypage/profileのようなお尻部分もつけるために "$1" をつけると、"content.example.com/var/www/html/mypage/profile"のようなアクセス先になってしまった
* httpdのRewriteRuleの仕様としてRewrite先が "/" から始まらない場合、自動でDocumentRootを差し込む作りになっている(と読んだように記憶しているのにリンクを見つけられていない......)
* 本当にアクセスさせたいリンクに書き換えるにはさらにここにRewriteRuleを適用すればいいのか......?

という感じで、事前設定した時間を切れたので諦めた。
幸い諦めるだけで済んだのは、今回そもそも使おうと思っていたアクセス先はOpenShiftの中のサービスとして公開しているもので、一方でRouteとして長ったらしい名前も公開していたので、その長ったらしい名前でまずはテストでもするか、と挙動確認をしようとしたところで止まっていたため。

OpenShift上で、短くなったサービス名に置き換えたらすんなり動いた。もやっとするけど、仕方がない。
RewriteCondあたりをうまく組み合わせれば良かったのかも。

この辺りが参考になる。

あとはその調査の中でhttpdをリバプロとして設定するための情報を公式が出していた。初めて見たよこれ。


2つ目はnginxで動かすパターン。
予備調査でこの辺りを見つけていて、参考に設定の実行など試していたけれど、リダイレクトがうまく発生しない、認証画面に遷移しないなど、ベーシックなところでつまずいてしまった。

この設定にはLuaが使われているのだけど、Luaをそもそも全然知らない中で設定を見ていくしんどさがあり、コンテナ向きかは議論の余地があれど、昔から馴染みのあるhttpdで進めていくのが賢明、と判断してこの道は諦めた。


やりたいことの優先度がある中で有限の時間で進めていくとなると、今回みたいに時間を区切って調査に入り込んでいく、時間を過ぎたら一旦引き上げて次の道へ、というやり方は、入り込み過ぎることを防ぐという点でいいのかもしれない。

とにもかくにも、Keycloakをhttpdでリバースプロキシーする設定ができて、とても快適だし不安感がなくて良い。
OpenAMよりもフレンドリーな設定画面なのも嬉しい。(かつて昔に客先にOpenAMを入れたことがあり当時はしんどかった......)

使用可能なマンパワー不足で調査しきれなかった場所は、いつか強くてニューゲーム、したいな。

posted on: https://blog.tkhm.dev/2020/11/keycloak.html