Ruby から Net::LDAP で ActiveDirectory にアクセスする

Ruby には LDAP 用の実装がいくつかあるみたいだけど、Net::LDAP (ruby-net-ldap) なら Pure Ruby の実装らしいので、とりあえずそれを使うことにしました。

ほとんど ActiveDirectoryサーバーを使ったLDAP認証(Rubyから) - 与太郎プログラマの日記 のコピペです。

require 'rubygems'
require 'net/ldap'

PORT   = 389
DOMAIN = 'ad.example.com'
SERVER = "domain-controller-hostname.#{DOMAIN}"
BASE   = 'CN=Users,DC=ad,DC=example,DC=com'

ldap = Net::LDAP.new :host => SERVER, :port => PORT, :base => BASE,
                     :auth => {
                       # ほんとはなんらかの閲覧用アカウントを指定するべき
                       :username => "Administrator@#{DOMAIN}",
                       :password => 'PASSWORD',
                       :method   => :simple,
                     }

raise 'bind failed' unless ldap.bind

entries = { }

ldap.open { |conn|
  filter1 = Net::LDAP::Filter.eq('sAMAccountName', 'dayflower')
  filter2 = Net::LDAP::Filter.eq('objectClass', '*')

  conn.search( :filter => filter1 & filter2 ) do |entry|
    entry.each do |field, value|
      entries[field] = value
    end
  end
}

require 'yaml'
y entries

(objectClass=*) なフィルタは(少なくともこの例では)いらない気もするんだけど、なんとなく残してます。

実行すると、

--- 
:memberof: 
- CN=Domain Admins,CN=Users,DC=ad,DC=example,DC=com
:instancetype: 
- "4"
:samaccountname: 
- dayflower
:cn: 
- Daily Dayflower

......

みたくでます。

お気軽ですね。試行錯誤するうえでは下手な LDAP クライアント使うより、いろいろ触れていいかも。

(おまけ)Redmine に ActiveDirectory のユーザ情報でログインする

なんでこんなことやったかというと、Redmine に AD の情報でうまくログインできなかったから。

LDAP認証 - RedmineガイドRedmineLDAP - Redmine が原文?)のとおりにやってみたらうまくいきませんでした。

例示の

名前 = My Directory
ホスト = host.domain.org
ポート = 389
LDAPS = no
アカウント = MyDomain\UserName
パスワード = <password>
Base DN = CN=users,DC=host,DC=domain,DC=org
LDAP認証 - Redmineガイド

になってるところ、Base DN が違ってて

Base DN = CN=users,DC=domain,DC=org

が正しいですね。うまくいくようになって見返してみたらこちらが正しいのは自明だけど、恥ずかしながら結構悩んでました。

あと、

注意: LDAP属性名は大文字・小文字を区別します。
(Note that LDAP attribute names are case sensitive.)

LDAP認証 - Redmineガイド

とあるけど、大文字小文字はたぶん区別しないんじゃないかな。