Shibboleth関連サーバをロードバランサの下に置く場合の注意


ShibbolethのIdPやSP等のサーバを、SSLのオフローディングや冗長化のためにロードバランサの下に置く場合の注意点をまとめてみます。

Shibboleth IdPのロードバランサー利用

RNAT or client-IP

サーバをロードバランサー配下に置く場合、クライアントのIPアドレスをソースに持ったままサーバに届く設定と、特定のHTTPヘッダにクライアントのソースIPアドレスを入れて、ソースアドレスはロードバランサー自身となるタイプの2種類の構成が考えられます。前者はデフォルトルートをロードバランサーにする必要があるため、ロードバランサーで一種のNATを行います。

個人的には後者のほうがネットワーク構成に対する制約が少なくて好きなのですが、Shibbolethをロードバランサーの下に入れる場合は圧倒的に前者がお勧めです。後者だと、Apache, mod_proxy_ajp, Tomcat, Shibboleth IdPの各段階で色々設定してソースアドレスをShibboleth IdPに届けないと、ShibbolethのログにソースIPアドレスが記録されません。しかもいろいろな制約条件があります。

一回挑戦してみたのですが、あまりに複雑になるので諦めました。普通にNATするほうが良いと思います(諸事情で、NAT構成にするためにサーバにNICを足す羽目になりましたが…)。

SSLオフローディングに関する問題

ここでは、ロードバランサーでSSLオフローディングを行い、Apacheのmod_proxy_ajpとTomcat上のShibboleth IdPを単純に組み合わせて、80/tcpでロードバランサ経由のリクエストを受ける場合を考えます。

この場合、ShibbolethはSSLが必須のため、ブラウザが認証画面に移った際に、”Error Message: Message did not meet security requirements”というエラーが出て利用できません。

また、Tomcatはセキュアな通信の場合CookieにSecure属性を付けるようですが、この機能も働かなくなります。

これは、tomcatのserver.xmlで、AJPコネクタの設定を次のように変更すれば解決します(前者に対応するのがproxyPortとscheme、後者に対応するのがsecure)。

変更前:

変更後:

これで、エラーメッセージは発生しなくなり、またJSESSIONIDのCookieだけではなく、_idp_authn_ic_keyのCookieにもSecure属性が付くようになります。

冗長化とIdPの情報同期の問題について

学認のサイトなどにIdP冗長化に関する様々な情報があります。たとえば、「IdP冗長化の方法と仕様書の書き方」には、Terracotta方式、Stateless Clustering方式、repcached(memcached)方式の3つが紹介されています。しかしこれらはどの方法も(Stateless Clusteringはだいぶマシですが)、性能の低下やシステム・運用の複雑化を招きます。

そもそもこれらの方法は何のために情報を同期しているかというと、IdPのサーバが切り替わった際にそのまま全てのユーザのセッションを継続できるということと思われます。もしかしたらSAML1的なバックチャネル接続にも関係するかもしれませんが、当方では現在、バックチャネル接続をサポートしていないので検証できません。

通常のSSLオフローディングが可能なロードバランサーは、クッキーを用いたパーシステンスをサポートしており、これを設定しておけば通常運用状態でセッション中に接続先のサーバが移り変わることはありません。

また、仮にサーバが移り変わり、セッションが継続できなくなった場合に何が起こるかというと、新たなサービスをSSOでユーザが利用したくなった時に、再認証が要求されるということだけで、これは通常の認証タイムアウトでも十分に起こることです。

したがって、サーバの運用が安定しており、SSLオフローディングが可能なロードバランサーが利用可能な状況で、(もしかすると不要な条件かもしれませんが)バックチャネル接続を利用しないならば、性能・構築・管理に関するコストを払ってまで、IdPサーバ同士で情報を同期する必要はありません。単純にクッキーによるパーシステンスを有効化し、素のIdPを並べるだけでほとんど問題は生じません。

モニターの設定

ロードバランサーがサーバの健康状態をチェックするためのモニターの設定ですが、80/tcpの死活監視だけでは、Apacheだけが生きていてもTomcat上のShibboleth IdPが死んでいる場合を検出できません。たとえば、次のような設定にすればApacheとShibboleth IdPの双方の死活監視が可能です(IdPメタデータのURLを利用しています)。

  • HTTP送信文字列: GET /idp/shibboleth
  • 受信文字列の部分一致条件: EntityDescriptor

Shibboleth SPのロードバランサー利用

RNAT or client-IP

Shibboleth SPにおいても、クライアントのIPアドレスはNATで取得するのがお勧めです。理由はIdPと同じで、複雑な設定になる上に制約が多いからです。

SSLオフローディングに関する問題

Shibboleth SPをロードバランサー配下に置く場合、shibboleth2.xmlで

のようにhandlerSSL=”false”にしてSSLなしでのセッションを許す必要があるのですが(また、後述のようにcookiePropsは”https”に設定することがお勧めです)、素直にこの状態でSSLオフローディング配下にSPを置くと、IdPから”No peer endpoint available to which to send SAML response”のようなエラーメッセージで怒られてしまいます。これはIdPのidp-process.logに残るエラーメッセージで見ると、

Relying party ‘https://ホスト名/shibboleth-sp’ requested the response to be returned to endpoint with ACS URL ‘https://ホスト名:80/Shibboleth.sso/SAML2/POST’  and binding ‘urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST’ however no endpoint, with that URL and using a supported binding,  can be found in the relying party’s metadata

No return endpoint available for relying party https://ホスト名/shibboleth-sp

のようなエラーが出ていることがわかります。要するにSPからエンドポイントは「https://ホスト名:80/Shibboleth.sso/SAML2/POST」だよ、という情報が来ているのにそんなエンドポイントがないよ、ということでエラーが出てしまっています。これを防ぐには、mod_shibが動いているApacheのhttpd.confで、

となっているところを無理やり、

にすれば動くようになります(ssl.confなどmod_sslの設定部分ではなく、グローバル設定の部分にあるServerNameを「https:」に設定するのです)。

shibboleth2.xml中の、<Sessions/>のcookieProps属性はhandlerSSLが”false”の状態でも”https”に設定して問題ありません。ちなみにこの設定を”https”にすると、Shibboleth SPのCookieにSecure属性が付きます。なので”https”に設定することがお勧めです。

冗長化とSP間の情報同期の問題について

IdPの場合と同様、Shibboleth SPの冗長化に関しても、学認・NIIのサイトに幾つか記述があります。たとえば、「ロードバランサー配下のシボレス SP 環境設定に関する検証実験」では、複数のSPサーバ上で1つしかshibdを起動しないことで、SPサーバ間での情報同期を実現しています。しかしこの方法ではshibdが冗長化されておらず、冗長度の点で問題があるといえるでしょう。

実はこれも、ロードバランサーによるクッキーによるパーシステンスが利用できる場合には、このような情報同期を考える必要はありません。それぞれのSPサーバにshibdを普通に起動し、単純にクッキーによるパーシステンスをロードバランサーに設定すれば、特に問題なくSPはシングルサインオンを実現可能です。冗長化レベルもshibdを1つしか起動しないのと比べて非常に高くなります。

モニターの設定

Shibboleth SPの場合は、次のようなモニター設定でApacheとshibdの死活監視が可能です(SPメタデータのURLを利用しています)。

  • HTTP送信文字列: GET /Shibboleth.sso/Metadata
  • 受信文字列の部分一致条件: EntityDescriptor

Shibboleth IdPが参照するLDAPサーバのロードバランサー利用

以前、Shibboleth IdP 2.3とOracleのJDK 1.6でIdPを構築した時は、LDAPサーバが切り替わっても自動的な再接続がなかなかされずにIdPがハングアップに近い状態になってしまうという現象がありました。この時は、IdPサーバ上に/usr/java/jdk1.6.*/jre/lib/jndi.propertiesというファイルを作成し、その中身を

のようにすることで、すぐに再接続するようになりました。

しかし先日、Shibboleth IdP 2.4とOpenJDK 1.7でIdPを構築した時は、このような設定を入れなくてもすぐに再接続してくれたように見えたので、もしかすると最近はこのような対処は不要なのかもしれません。

Shibboleth関連サーバをロードバランサの下に置く場合の注意」への1件のフィードバック

  1. ピンバック: Shibboleth IdPのログをPostgreSQLに格納する | 慶應義塾ITC本部・技術メモ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です