【IT備忘録】 Apache2 への mod_auth_mellon 導入 (その弐) | 仕事の覚書き

仕事の覚書き

メモメモ

0. 現在の状況

現在の状況は…と言うと、クライアントマシンのブラウザから、SP である mod_auth_mellon を組み込んだ Apache にアクセスするところまで。 ここで IdP への認証要求を起こすために、ブラウザから https://www.example.com/protected/ の要求を発行するが、これに対しては 「500 Internal Server Error」 が返ってきて終わってしまう(涙);

このときにブラウザに戻されるリダイレクト表示をみると、「https://www.example.com/protected/endpoint/login?ReturnTo=https%3A%2F%2Fwww.example.com%2Fprotected%2F&IdP=(null)」 となっている。認証を促す login? や、戻り先の ReturnTo の指示は何となく OK っぽいが、IdP の先が (null) となっているのは問題である。
これは、まだ mod_auth_mellon の設定に問題があるということに他ならない。

1. SAML 2.0 のフェデレーションの流れ

ここで、SAML2.0 の動作について、再度きちんとおさらいしておくことにする。導入前であれば単なる技術うんちく記事に過ぎないが、実際のシステム稼動を目標にすると、少なくとも、ここで紹介する @IT の記事内容あたりはきちんと把握しておく必要がある…というのが、当事者としての実感である。
SAML2.0 のフェデレーションにおける、大きなトランザクションの流れは、下図のようになる:

 

この図の詳しい解説は、この図を引用させて貰った @IT の記事 「クラウド・コンピューティング時代の認証技術」 を参照して貰うこととして、重要なのは、ユーザの能動的動作 (1) に対して、(2) のリダイレクト、(4) のポストはウェブの http ベースのプロトコルであるというところである。
IdP の何処にどのようにリダイレクトするべきかを IdP があらかじめ IdP のメタデータに記述しておかなければ SP は適切に要求をリダイレクト出来ないし、同様に (2) でリダイレクトされた IdP は、SP が適切に SP のメタデータを記述しておかないと、(3) の後、どのように認証結果を報告したら良いのかが解からない訳である。

上記の記事の先を読むと、次に メッセージのシーケンス図 が出てくる。あまり、図のみを引用すると著作権で文句を言われそうなので、これから先はリンクに留めるが、これを見る限りにおいては、IdP と対話している http プロトコルの相手は、SP ではなく、エンドユーザのブラウザ であるということである。

2. 再度細かく調査する

いかんせん情報量が少なく、頼りになるのは添付の README くらいのもの。めげることなく調べていると、GitHubGeneric setup instructions のところに mod_create_metadata.sh という、秘密鍵・証明書からメタデータまでを簡単に作成してくれるスクリプトがあることが判明。
また、この解説中、Feide がテスト用に提供する test-IdP のメタデータの取得方法が記述されている。この環境は多分、simpleSAMLphp で接続した先と同じところであると思われる。
早速、その記述に従い、https://idp-test.feide.no/simplesaml/saml2/idp/metadata.php と打ち込んで simpleSAMLphp ベースの Feide のテスト用 IdP のメタデータを取得する。 メタデータ中の証明書などの情報を省略したものが、下記である:

<md:EntityDescriptor
    xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    entityID="https://idp-test.feide.no">
  <md:IDPSSODescriptor
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
     <md:KeyDescriptor use="signing">...</md:KeyDescriptor>
     <md:KeyDescriptor use="encryption">...</md:KeyDescriptor>
     <md:SingleLogoutService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        Location="https://idp-test.feide.no/simplesaml/saml2/idp/SingleLogoutService.php"/>
     <md:NameIDFormat>
        urn:oasis:names:tc:SAML:2.0:nameid-format:transient
     </md:NameIDFormat>
     <md:SingleSignOnService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        Location="https://idp-test.feide.no/simplesaml/saml2/idp/SSOService.php"/>
  </md:IDPSSODescriptor>
  <md:Organization>
     <md:OrganizationName xml:lang="en">Feide</md:OrganizationName>
     <md:OrganizationName xml:lang="no">Feide</md:OrganizationName>
     <md:OrganizationDisplayName xml:lang="en">
        Feide - Norwegian educational institutions (test-IdP)
     </md:OrganizationDisplayName>
     <md:OrganizationDisplayName xml:lang="no">
        Feide - Norske utdanningsinstitusjoner (test-IdP)
     </md:OrganizationDisplayName>
     <md:OrganizationURL xml:lang="en">
        http://www.feide.no/introducing-feide
     </md:OrganizationURL>
     <md:OrganizationURL xml:lang="no">
        http://www.feide.no/
     </md:OrganizationURL>
  </md:Organization>
  <md:ContactPerson contactType="technical">
     <md:GivenName>Feide</md:GivenName>
     <md:SurName>Support</md:SurName>
     <md:EmailAddress>moria-drift@uninett.no</md:EmailAddress>
  </md:ContactPerson>
</md:EntityDescriptor>

上記の記述を見て、まず、entityID の記法と IDPSSODescriptor 記述内の SingleSignOnService SingleLogoutService Location 記述は、同じ simpleSAMLphp ベースの IdP メタデータ記述であるだけに十分参考になりそうである。

3. 基本に立ち返ることの重要さ(苦笑)

やはり基本は、用意されているデバッグオプションを立てるなりして、動作状況を追うこと…に尽きる。今回のケースでは、Apache の httpd.conf 中に MellonSessionDump だの MellonSamlResponseDump といったディレクティブが用意されているのである。こういう場合は、やはり、このような機能を使うに越したことはない。

MellonSessionDump を On にして再度 Apache を起動し直し、ブラウザより mod_auth_mellon を組み込んだ Apache に対し 「https://www.example.com/protected/」 と打つと /var/log/httpd 下のログファイルの日時が更新される。早速 errorlog の内容を見てみると、lasso 内の処理で、何と libxmlsec-openssl から xmlsec が見つからないと言う。
想定外の事態で調べていくと 「xmlsec1 のバグ」 で、それもつい最近に見つかったようである。筆者が使っているのは最新ではないものの、幸か不幸か、その 修正リリース が終わってまだ1ヶ月も経っていない状況である(苦笑)

早速、問題のパッケージを入れ替えようとするが依存性があって上書き出来ない。何か上手いやり方があるのかも知れないが、仕方なく、昨日の記事に書いたインストールパッケージを全部削除し、再度新しいものを入れていく。問題部分は、昨日の記事でリンクが張られていないその他のパッケージの部分で、リンクが張られている lasso と mod_auth_mellon は同じものを使う。

入れ替えた後、mod_auth_mellon の構成ファイルをチェックすると全部消えている★★★
実は、昨日の記事では、/etc/httpd/conf の httpd.conf に定義設定を書く…と書いたが、conf.d のディレクトリ下に auth_mellon.conf が出来ていたので、こちらに全部移し変えてしたのである(涙)
それが、mod_auth_mellon の再インストールによって、初期状態のファイルに書き換えられてしまったようである(涙) 「まったく以って最悪!」 である プンプン#

仕方がないので、気を取り直して、きちんと丁寧に SP のメタデータを作成。これは、mellon_create_metadata.sh の中身を弄って、前々回?か前に作成した証明書と鍵を流用するようにスクリプトに手を加える。そのシェルでメタデータを生成し、エンティティ ID などを若干修正する。
/etc/httpd/conf.d 下の auth_mellon.conf 内の記述は再度打ち直しである(苦笑)
そして再度 Apache をリスタートすると…

今までは、「https://www.example.com/protected/endpoint/login?ReturnTo=https%3A%2F%2Fwww.example.com%2Fprotected%2F&IdP=(null)」 となっていたものが、「https://www.example.com/mellon/endpoint/login?ReturnTo=https%3A%2F%2Fwww.example.com%2Fprotected%2F&https%3A%2F%2Flogin.example.com
のように正しく書き換わっている♪
インストールしたパッケージ内のバグもあったが、原因はそれ以外にも、メタデータのLocation 記述ミスもあったことになる 。

4. 変更点のおさらい

あらためてインストールし直したパッケージのバージョンについては、前回の記事内容を修正しておく。これ以外の修正変更を含む作業手順は以下のとおり:

4.1 mellon_create_metadata.sh の修正

openssl コマンドで秘密鍵と自己署名の証明書を作成している部分をコメントアウトし、代わりに既存の鍵と証明書を、スクリプト上で指定された場所に、指定された名称で複製しておく。
修正の後、「mellon_create_metadata.sh urn:myhost https://myhost/mellon」 と入力する。
これは、mod_auth_mellon の Generic setup instructions に書かれているとおりである。 
この後、作成されたメタデータの内容を確認し、entityID については https://www.example.com の形式に修正しておく。

4.2 /etc/httpd/conf.d の auth_mellon.conf の修正?

前の記事と異なる部分は、MellonVariable を "cookie" から "saml" と MellonUser を "NAME_ID" から "user" に、MellonEndpointPath を "/protected/endpoint" から "/mellon/endpoint" に変えたところ。後は MellonIdP "IDP" を追加したことぐらいである。
MellonRequire や MellonDiscoveryURL などは排除してある。
「simpleSAMLphp> HOWTO for configuring known SPs with simplesamlphp IdP」

5. 今後の課題

一応、url 上に IdP=(null) が表示されるという IdP 不明という異常な状態からは解放されたものの、現時点では、ブラウザが IdP にリダイレクトされない…という問題が残っている。
現時点での Apache のログからは、ssl 関連のログに SSL ベースでの要求 「"GET /mellon/endpoint/login?ReturnTo=https%3A%2F%2Fwww.example.com%2Fprotected%2F&IdP=https%3A%2F%2Flogin.example.com HTTP/1.1" 302」 に対して、「Endpoint "endpoint/login" not handled by mod_auth_mellon」 というエラーが出て、404 エラー表示の後、そのまま終了…というか放置の状況になっている。

この間、simpleSAMLphp は何の反応もないので、まだ、IdP アクセスには至っていない。

次回はこの辺を調査する。