2010-10-25

ActvieDirectoryでケルベロス認証して、その結果をrailsで使ってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
railsには便利な認証機構がいろいろある感じですが、ActiveDirectoryに認証を任せるには普通はldapを使うのでしょうが、都合によりActiveDirectoryのldapがうまく使えないためケルベロス認証させたいときお話です。

調べ見たところ、もうそこはrailsではなくapacheの方でmod_auth_kerbを利用して認証させて、その結果がREMOTE_USERに設定されるので、その値を利用して認可するというやり方をするようです。
このやり方であればapacheのモジュールで認証できる仕組みならば、rails側に持ってくることもできそうです。

なので使えるようにしてみました。
環境は、CentOS5.4,apache2.2,passengerを利用した環境です。
ちなみにpassengerを使わずにapacheをproxyにして別のwebサーバを利用している時は、mod_rewriteを使ってREMOTE_USERが後ろのサーバに伝播されるような設定が必要なようです。

まずは、mod_auth_kerbの準備です。
[/etc/krb5.confの設定]
http://junsan45.blogspot.com/2009/10/centos-53-windows.html
などを見て、環境にあわせて/etc/krb5.confを設定してください。
ここで設定したrealmの値を後で使います。

[インストール]
su
yum -y install mod_auth_kerb

[設定]
vi /etc/httpd/conf.d/auth_kerb.conf
とりあえずテスト用に以下のような感じで設定
-----------------------------
<Location /test_krb_auth>
AuthType Kerberos
AuthName "Kerberos Login"
KrbAuthRealms [/etc/krb5.confで設定したrealm]
KrbVerifyKDC Off
KrbMethodNegotiate Off
require valid-user
</Location>
-----------------------------

[確認]
これで対象のサイトにログインした際に
これでREMOTE_USERに
username@realm
のようにrealm付きで認証したユーザがセットされることをお手軽に確認できる方法で確認します。

[おまけ]
mod_auth_kerbのversionが5.4
ならば
KrbLocalUserMapping On
とすることで
上記の@以降のrealmが除去される模様です。
yumでインストールされるversionは5.4より古かったです。


ここでrailsアプリを用意してpassengerの設定を行います。
passenger.confに以下のような感じでrailsアプリを利用できるように配置します。

RailsBaseURI /rails_kerb

<Location /rails_kerb>
AuthType Kerberos
AuthName "Kerberos Login"
KrbAuthRealms [/etc/krb5.confで設定したrealm]
KrbVerifyKDC Off
KrbMethodNegotiate Off
require valid-user
</Location>

これでrailsのApplicationControllerで
login = request.env['REMOTE_USER']
でユーザ情報を受け取り、データベースでも見て利用可能なユーザかどうかをチェックすればOKです。

本番環境はこれでよいのですが開発環境ではwebサーバでapacheを利用することはあまりないと思うので、REMOTE_USERが取得できないというのが困った感じです。
とりあえず以下のような感じで環境がdevelopmentの時だけ、独自のBASIC認証をしてREMOTE_USERをセットするようにしてみました。

class ApplicationController < ActionController::Base
  before_filter :authorize
  protected
  def authorize
    auth_ret = true
    if session[:user].nil?
      if ENV['RAILS_ENV'] == "development"
        auth_ret = false
        authenticate_or_request_with_http_basic do |user, pass|
          request.env['REMOTE_USER'] = user
          true
        end
      end
      login = request.env['REMOTE_USER']
      //本当はここいら辺でloginを利用して値をチェック
      session[:user] = login
    end
    if auth_ret and session[:user].nil?
      //認可されなかったときの処理
    end
  end
end
auth_retは、
if ENV['RAILS_ENV'] == "development"
の中に入るけど
authenticate_or_request_with_http_basic do |user, pass|
の中に入らない動きを見せたので入れてみました。

これでdevelopment環境でもREMOTE_USERが設定されるようになりました。
test環境を加えてもよいのかもしれないです。
コメントを投稿