LDAP認証時の複数ホスト指定について

1,072 views
Skip to first unread message

くるくる

unread,
Aug 19, 2009, 12:22:49 AM8/19/09
to Redmine Users (japanese)
グループの皆様、こんにちは。
たびたびお世話になっております、くるくると申します。

現在、ユーザ認証にLDAPを利用しています。

LDAPのソース(サーバ)は、ユーザ毎に個別に指定できるので、Redmineのドキュメントの通り、確かに『複数LDAP対応...』ではあるので
すが、1つのLDAPの設定に、複数のホスト名(やIPアドレス)を指定することは出来ないのでしょうか。

一応、Redmineのソースを見てみたところ、Net::LDAPというモジュールを使っているようです。

同名のモジュールだと、Perl版は複数ホストを指定できるようですが、Ruby版は検索しても複数指定OKという記載は発見できず、やはり、NGなの
かな...と思いました。

1つめのLDAPでNGだったら、2つめにフェイルオーバーさせるような設定は、クライアント側では難しいのでしょうか。

やはり、LDAPサーバ側で、クライアントに意識させない冗長構成を採るほうが良いのでしょうか。

皆様何か工夫されていましたら、教えていただければ幸いです。

hiro

unread,
Aug 19, 2009, 9:25:16 PM8/19/09
to Redmine Users (japanese)
こんにちは.

LDAPのレプリケーションに対応したいということですよね?
タイムアウトの制御ができないようなので微妙ですが,
以下のようにするとどうでしょう.

・ホスト名をカンマ区切りで複数指定可能
・最初に接続成功したホストを選択(全部失敗なら最初のホスト)

Index: app/models/auth_source_ldap.rb
===================================================================
--- app/models/auth_source_ldap.rb (リビジョン 2838)
+++ app/models/auth_source_ldap.rb (作業コピー)
@@ -87,6 +87,21 @@
:encryption => (self.tls ? :simple_tls : nil)
}
options.merge!(:auth => { :method => :simple, :username =>
ldap_user, :password => ldap_password }) unless ldap_user.blank? &&
ldap_password.blank?
+
+ # LDAP host comma separable
+ hosts = self.host.split(",")
+ if hosts.size > 1
+ # select first live host or first host
+ options[:host] = hosts.find {|h|
+ begin
+ Net::LDAP.new(options.merge(:host => h)).open {}
+ true
+ rescue Net::LDAP::LdapError
+ false
+ end
+ } || hosts.first
+ end
+
Net::LDAP.new options
end

くるくる

unread,
Aug 20, 2009, 3:22:14 AM8/20/09
to Redmine Users (japanese)
hiro さま、こんにちは。

コードのサンプルまでつけて下さって、ありがとうございます!
ちょっと試してみます。

本日は時間切れなので、うまく動きましたら、また報告させていただきます!
> > 皆様何か工夫されていましたら、教えていただければ幸いです。- 引用テキストを表示しない -
>
> - 引用テキストを表示 -

くるくる

unread,
Aug 24, 2009, 1:42:22 AM8/24/09
to Redmine Users (japanese)
こんにちは、くるくるです。
先ほど、コードのチェックをしてみました。

残念ながら、Net::LDAPの問題だと思うのですが...。
タイムアウトの設定や、エラーの原因の特定が難しいため、複数エントリを記載し、最初に接続NGになるアドレスを書くと、プログラムがずっと処理中でレ
スポンスが返ってきませんでした。

最初に必ずOKになるエントリを記載した場合は、問題ないのですが。


カンマ区切りの1つ1つのホストに対し、LDAPの openを実施しようとするので、
NGのホストに対しOpenを行おうとすると、そのままだんまりになります。

-----------------------
begin
Net::LDAP.new(options.merge(:host => h)).open {}
true
-----------------------

Net::LDAPだけでは難しい気がしたので、事前に別のモジュール(Socketとかを扱えるもの)で、すくなくとも簡単な接続確認を行う必要があ
るのかな、と思いました。

もしくは、ActiveLDAPというのを利用すれば、タイムアウトの設定などが使えるのかもしれません。
まだそこまでRubyに詳しく無いので、手が回らないのですが...。


くるくる のメッセージ:

hiro

unread,
Aug 24, 2009, 4:10:29 AM8/24/09
to Redmine Users (japanese)
こんにちは.

ではLDAPライブラリを使わずにSocketで直接接続テストしてみるとどうでしょうか?
タイムアウト時間は適当に弄ってください.

Index: app/models/auth_source_ldap.rb
===================================================================
--- app/models/auth_source_ldap.rb (リビジョン 2838)
+++ app/models/auth_source_ldap.rb (作業コピー)
@@ -17,6 +17,8 @@

require 'net/ldap'
require 'iconv'
+require 'timeout'
+require 'socket'

class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login
@@ -87,6 +89,21 @@
:encryption => (self.tls ? :simple_tls : nil)
}
options.merge!(:auth => { :method => :simple, :username =>
ldap_user, :password => ldap_password }) unless ldap_user.blank? &&
ldap_password.blank?
+
+ # LDAP host comma separable
+ hosts = self.host.split(",")
+ if hosts.size > 1
+ # select first live host or first host
+ options[:host] = hosts.find {|h|
+ begin
+ timeout(0.5) { TCPSocket.new(h, self.port).close }
+ true
+ rescue Timeout::Error, StandardError
+ false
+ end
+ } || hosts.first
+ end
+
Net::LDAP.new options
end

Reply all
Reply to author
Forward
0 new messages