プロジェクトをまたいで自分に関連するチケットをリストアップできる、という点に興味があり、巷でウワサのredMineをたててみる。
LDAPに既に存在するアカウントでログインできる、という点も魅力だ。

環境


redMine環境は、FC5、ruby-1.8.5.35-2.fc5、rails (1.2.3)、mongrel (1.0.1)、mongrel_cluster (1.0.2)、redMine-0.5.1。
Active DirectoryはW2k3で動作。ユーザの姓名には日本語を指定しており、表示名が「赤峰 るび夫」のようになる運用をしている。ログオン名は姓名とは別の英数字IDを任意で指定している。

ADドメインはad.example.comとする。

redMineの設定

  • adminでredMineにログイン
  • 管理>認証>新しい認証モード
  名前:適宜。ADドメイン(のNTドメイン表現)と同じにした。
  ホスト:ADサーバホスト名。
  ポート:389
  アカウント:cn=表示名, cn=Users, dc=ad, dc=example, dc=com
  • このユーザはredmineの認証用に作成した。試行錯誤の過程で英字で姓のみのユーザを作成した。後述のinitialize_ldap_conの関係で日本語姓名だとbindできない様子。
  • ディレクトリに対する匿名アクセス可能なアカウントを作った方がよかったかも。
  パスワード:上記ユーザのパスワード
  BaseDN:cn=Users, dc=ad, dc=example, dc=com

あわせてユーザを作成:true
ログイン:sAMAccountName
→ADユーザのプロパティでは、「アカウント ユーザログオン名」
名前:givenName
→ADユーザのプロパティでは、「名」
苗字:sn
→ADユーザのプロパティでは、「姓」
メールアドレス:mail
→ADユーザのプロパティでは、「電子メール」

  • アスタリスクが必須項目マークだと思うんだけど、マークに従えば、ログインだけ指定すればいいことになる。のだけど、テーブルを見るとNotNull制約みたいなので、4項目とも設定した。
  • AD側のユーザも合わせて上記項目を埋めた。

mysql> desc users;
+-------------------+-------------+------+-----+---------+----------------+
| Field             | Type        | Null | Key | Default | Extra          |
+-------------------+-------------+------+-----+---------+----------------+
| id                | int(11)     | NO   | PRI | NULL    | auto_increment |
| login             | varchar(30) | NO   |     |         |                |
| hashed_password   | varchar(40) | NO   |     |         |                |
| firstname         | varchar(30) | NO   |     |         |                |
| lastname          | varchar(30) | NO   |     |         |                |
| mail              | varchar(60) | NO   |     |         |                |
| mail_notification | tinyint(1)  | NO   |     | 1       |                |
| admin             | tinyint(1)  | NO   |     | 0       |                |
| status            | int(11)     | NO   |     | 1       |                |
| last_login_on     | datetime    | YES  |     | NULL    |                |
| language          | varchar(5)  | YES  |     |         |                |
| auth_source_id    | int(11)     | YES  |     | NULL    |                |
| created_on        | datetime    | YES  |     | NULL    |                |
| updated_on        | datetime    | YES  |     | NULL    |                |
+-------------------+-------------+------+-----+---------+----------------+

  • 認証モードを保存して一覧に戻る。
  • 「テスト」をクリックして「接続しました。」が表示されることを確認する。

ログイン失敗

これで上手くいくかなーと思ったら、ログインできない。
production.logを見たらiconvがこけてるらしい。

Processing AccountController#login (for *.*.*.* at 2007-09-19 18:43:52) [POST]
  Session ID: feb2a36cbb1a47dd7b0396964d0185e3
  Parameters: {"action"=>"login", "controller"=>"account", "password"=>"[FILTERED]", "login"=>"ログインID"}


Iconv::IllegalSequence ("姓 名,CN"...):
    /app/models/auth_source_ldap.rb:72:in `iconv'
    /app/models/auth_source_ldap.rb:72:in `initialize_ldap_con'
    /app/models/auth_source_ldap.rb:47:in `authenticate'
    (略)



認証モードの設定で、ログイン=sAMAccountNameとしていて日本語周辺は回避した、と思っていたのだが、内部的に以下のような流れらしい。
  1. 認証モードで「アカウント」に指定したDNとパスワードでLDAPに接続
  2. この接続を使って、redmineのログインID==sAMAccountNameとなるエントリを問い合わせる。
  3. 問い合わせた結果得られたDN+ログインフォームに入れたパスワードで再度LDAPに接続
  4. 接続できたら認証OK
なので、(ここの運用だと)3のDNに日本語が含まれ、これをiso-8859-15→utf-8変換しようとしてiconvで死ぬ。ということみたい。

とりあえず回避

場当たり的に、ADからの応答もutf-8だと決めてかかることに。
app/models/auth_source_ldap.rbをちょこっと書き換え。

private
  def initialize_ldap_con(ldap_user, ldap_password)
    Net::LDAP.new( {:host => self.host,
                    :port => self.port,
                    #:auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }}
                    :auth => { :method => :simple, :username => ldap_user, :password => ldap_password }}

    )
  end

おわり

mongrel_clusterをrestartし、再度ログインフォーム。
ADユーザのログオン名+パスワードでredMineにログインできた。
ふー。

でも「あるAD上のグループに属しているユーザだけredMineを使える」みたいなコントロールはよくわからず。
うーん。