Your SlideShare is downloading. ×
0
Ruby で扱う LDAP のススメ
  - Ruby meets LDAP -
      その選択肢と事例
    - Choices and cases –

    高瀬一彰 / @tasheeen
Who?
高瀬一彰 (Kazuaki Takase)
エイケア・システムズ株式会社
Lang: perl→php→ruby+javascript
Rails で LDAP 管理アプリ
Why?
Ruby with LDAP に関する情報の不足
LDAP 自体がマイナー
Ruby コミュニティに、LDAPを扱うため
の入り口となる情報を提供したい
 LDAPって?
 どんなライブラリがあるの?
 どれを使えばいいの?
What?
LDAP の概略
LDAP ライブラリの紹介
事例紹介
コード例
参考資料一覧
LDAPの概略
LDAPの概略(1)
Keywords
  LDAP
  Entry
  ObjectClass
  Attribute
  DIT
  Distinguished Name
LDAPの概略(2)
Lightweight Directory Access Protocol
  RFC4510などで定義
  元々は DAP。その軽量版(=Lightweight)
  Directory = 台帳・名簿
  何でも登録可...
LDAPの概略(3)
Entry
 LDAPにおけるデータの基本単位
   =台帳の登録単位。名簿なら「人」
   ≒RDBにおける行に近い
 現実世界の「物(=オブジェクト)」を表す
 エントリは属性を持つ
   「人」に対する「名前」「電話...
LDAPの概略(4)
Object Class
 エントリが「何」か
   OOP の「クラス」と同義
 オブジェクトクラスに
 よって持てる属性が変わる
 Unix アカウントのエント
 リなら posixAccount
 継承・抽象型・構造...
LDAPの概略(5)
Attributes
  一つの属性に複数の値
  を持っている場合が多
  い
  台帳・名簿としての
  考え方
LDAPの概略(6)
Directory Information Tree (DIT)
  ディレクトリデータベースを DIB
  ツリー構造していると DIT
  階層的に管理するのがコンセプト
  エントリがツリーとして連なる
LDAPの概略(7)
Distinguished Name(DN)
  Rlative Distinguished
  Name(RDN)
    その階層における一意の
    名前
      cn=Ruby Taro
    エントリが持...
Ruby with LDAP
Ruby with LDAP - libs



Obsolete !




Obsolete !
Ruby with LDAP - libs



               RFC 1823の実装             Pure Ruby.             ActiveRecordのLDAP版
 character     拡...
Ruby with LDAP – ruby-ldap
ruby-ldap
 RFC1823 (The LDAP Application Programming Interface)
 のRuby版実装
 使い方は同梱のテストが参考になる
 速い...
Ruby with LDAP – net-ldap
net-ldap
 Pure Ruby な LDAP API 実装
 ポータビリティに富む
 RDoc のドキュメントが結構しっかりしている
   bind

  search

   add...
Ruby with LDAP - activeldap
activeldap
 ActiveRecord を参考に作られた、LDAP API
 ruby-ldap や net-ldap, JNDI を内部的に利用
 クラスはツリーを抽象、インス...
Cases
Case 1
   事例提供者:カピバラさん
http://sites.google.com/site/capibaraproject/home
Case カピバラさん
背景
社内の各システム毎にID情報が分散
既存のLDAPサーバがあった
 既存の構造的には認証統一には難しかった
新規にLDAP作成
管理アプリ作成
 管理
     ユーザ一覧/検索/新規作成/所属変更
     パス...
Case カピバラさん




パスワード初期化

ユーザ管理         パスワード変更
 一覧
 検索
 新規作成
 所属変更
Case カピバラさん
ruby-ldap
 ActiveLdap は使いづらかったそうで回避(泣
   確かに ruby-ldap の方がプリミティブな実装
 ruby-ldapに限らず、LDAPについても情報が
 不足して困った
 速度面・...
Case 2
事例提供者:岡澤さん
http://d.hatena.ne.jp/yujiorama/
Case 岡澤さん
ruby-ldap を利用
分散した社員マスタ/認証を統合




アカウント
 作成・編集・削除                  パスワード変更など
ML
 依頼があり次第        管理作業   参照できる
 作成...
Case 岡澤さん
ruby-ldap
 元々作った人が「Rails 関連は面倒」(笑
 openldap のコマンドとほぼ同じような作り
 で、コマンドの使い方が判ると直観的に使え
 た
 同様の理由で、デバッグ等もやりやすかった
Case 3
事例提供者:谷口さん
Case 4
事例提供者:高瀬
Case 高瀬
activeldap
アカウント/権限管理




            sync
                                     batch
 ユーザ管理                      ...
Case 高瀬
activeldap
 Rails の機能を活用したかった
 script/runner でライブラリ使えるの便利
 validation や association 使えるの便利
   validationは作りによってはとっ...
Code Examples
Code Examples – ruby-ldap (1)
Connection and Bind
  LDAP::Conn.new / LDAP::Conn#bind
  @conn = LDAP::Conn.new('localhost',...
Code Examples – ruby-ldap (2)
search
  LDAP::Conn#search
  @conn.search("o=RubyKaigi2010,c=jp", LDAP::LDAP_SCOPE_SUBTREE,
...
Code Examples – ruby-ldap (3)
Add
 LDAP::Conn#add
  entry = {"objectclass" => ["top", "person"],
            "cn" => ["Rub...
Code Examples – ruby-ldap (4)
Modify
  LDAP::Conn#modify
  mod_hash = {"sn" => ["hoge", "taro"]}

  @conn.modify("cn=Ruby ...
Code Examples – ruby-ldap (5)
Gathering Error Information
  LDAP::Error
  begin
    @conn.delete("cn=Ruby Taro,o=RubyKaigi...
Code Examples – net-ldap(1)
Connection and BIND
 Net::LDAP.new
  @ldap = Net::LDAP.new :host => 'localhost',
             ...
Code Examples – net-ldap(2)
search
  Net::LDAP#search
  @ldap.search # => [#<Net::LDAP::Entry: ...>, #<Net::LDAP::Entry .....
Code Examples – net-ldap(3)
Add
 Net::LDAP#add
 attrs = {
   :objectclass => ["top", "inetOrgPerson", "posixAccount"],
   ...
Code Examples – net-ldap(4)
Modify
  Net::LDAP#modify
  dn = "uid=ruby_taro,ou=Users,o=RubyKaigi2010,c=jp"

  opts = [
   ...
Code Examples – net-ldap(5)
Gathering Error Information
  Net::LDAP#get_operation_result
  @ldap.add(:dn => dn, :attr => a...
Code Examples – activeldap(1)
Connection and Bind
  ActiveLdap::Base.setup_connection
  ActiveLdap::Base.setup_connection ...
Code Examples – activeldap(2)
Mapping
 define subclass
 class User < ActiveLdap::Base
   ldap_mapping :prefix => "ou=Users...
Code Examples – activeldap(3)
Search
 ActiveLdap::Base.find
  User.find(:all) # => [#<User ...>, #<User ...>, ...]
  User....
Code Examples – activeldap(4)
Add/Modify
 ActiveLdap::Base#save , save!
  user = User.new :sn => 'Ruby', :cn => "Ruby Taro...
Code Examples – activeldap(5)
Gathering Error Information
  ActiveRecord::Validations#errors
  user = User.new :sn => 'Rub...
参考資料
参考資料
LDAP         RFC 4510
             http://datatracker.ietf.org/doc/rfc4510/

             Rubyist Magazine - ActiveLd...
ありがとうございました
   Thank you.
Upcoming SlideShare
Loading in...5
×

Ruby で扱う LDAP のススメ

14,958

Published on

RubyKaigi2010 企画 ”Ruby で扱う LDAP のススメ”資料です。

数例ある事例紹介の内、谷口さんの事例紹介のスライドは以下にあります
http://www.slideshare.net/tasheeen/active-ldap

Published in: Technology
1 Comment
8 Likes
Statistics
Notes
  • RubyKaigi2010 企画 ”Ruby で扱う LDAP のススメ”資料です。

    数例ある事例紹介の内、谷口さんの事例紹介のスライドは以下にあります
    http://www.slideshare.net/tasheeen/active-ldap
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
14,958
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
44
Comments
1
Likes
8
Embeds 0
No embeds

No notes for slide

Transcript of "Ruby で扱う LDAP のススメ"

  1. 1. Ruby で扱う LDAP のススメ - Ruby meets LDAP - その選択肢と事例 - Choices and cases – 高瀬一彰 / @tasheeen
  2. 2. Who? 高瀬一彰 (Kazuaki Takase) エイケア・システムズ株式会社 Lang: perl→php→ruby+javascript Rails で LDAP 管理アプリ
  3. 3. Why? Ruby with LDAP に関する情報の不足 LDAP 自体がマイナー Ruby コミュニティに、LDAPを扱うため の入り口となる情報を提供したい LDAPって? どんなライブラリがあるの? どれを使えばいいの?
  4. 4. What? LDAP の概略 LDAP ライブラリの紹介 事例紹介 コード例 参考資料一覧
  5. 5. LDAPの概略
  6. 6. LDAPの概略(1) Keywords LDAP Entry ObjectClass Attribute DIT Distinguished Name
  7. 7. LDAPの概略(2) Lightweight Directory Access Protocol RFC4510などで定義 元々は DAP。その軽量版(=Lightweight) Directory = 台帳・名簿 何でも登録可能 台帳として最適化したデータ構造を持つ
  8. 8. LDAPの概略(3) Entry LDAPにおけるデータの基本単位 =台帳の登録単位。名簿なら「人」 ≒RDBにおける行に近い 現実世界の「物(=オブジェクト)」を表す エントリは属性を持つ 「人」に対する「名前」「電話番号」etc. RDB と違う点 エントリがスキーマを持つ
  9. 9. LDAPの概略(4) Object Class エントリが「何」か OOP の「クラス」と同義 オブジェクトクラスに よって持てる属性が変わる Unix アカウントのエント リなら posixAccount 継承・抽象型・構造型・補 助型などの概念とルール posixAccountは補助型 person 等と組み合わせる
  10. 10. LDAPの概略(5) Attributes 一つの属性に複数の値 を持っている場合が多 い 台帳・名簿としての 考え方
  11. 11. LDAPの概略(6) Directory Information Tree (DIT) ディレクトリデータベースを DIB ツリー構造していると DIT 階層的に管理するのがコンセプト エントリがツリーとして連なる
  12. 12. LDAPの概略(7) Distinguished Name(DN) Rlative Distinguished Name(RDN) その階層における一意の 名前 cn=Ruby Taro エントリが持つ任意の属 性がRDNになる RDNを下から一番上まで cn=Ruby Taro,o=RubyKaigi2010,c=jp 繋げるとツリーで一意に 特定される名前になる (DN)
  13. 13. Ruby with LDAP
  14. 14. Ruby with LDAP - libs Obsolete ! Obsolete !
  15. 15. Ruby with LDAP - libs RFC 1823の実装 Pure Ruby. ActiveRecordのLDAP版 character 拡張ライブラリ Rails と相性がいい 抽象度が高い ruby-ldap より10倍程 net-ldap よりも3倍程度 weak point ドキュメントが少ない 度遅い 遅い advantage 速い! ポータビリティが高い 高度な抽象化と豊富な機能 install gem install ruby-ldap gem install net-ldap gen install activeldap for use require “rubygems” require “rubygems” require “rubygems” require “ldap” require “net-ldap” require “active_ldap”
  16. 16. Ruby with LDAP – ruby-ldap ruby-ldap RFC1823 (The LDAP Application Programming Interface) のRuby版実装 使い方は同梱のテストが参考になる 速い! bind search add modify C Extension etc…
  17. 17. Ruby with LDAP – net-ldap net-ldap Pure Ruby な LDAP API 実装 ポータビリティに富む RDoc のドキュメントが結構しっかりしている bind search add modify Pure Ruby etc…
  18. 18. Ruby with LDAP - activeldap activeldap ActiveRecord を参考に作られた、LDAP API ruby-ldap や net-ldap, JNDI を内部的に利用 クラスはツリーを抽象、インスタンスはエントリを抽象 ActiveLdap::Base find User new (Subclass) cn= save destroy
  19. 19. Cases
  20. 20. Case 1 事例提供者:カピバラさん http://sites.google.com/site/capibaraproject/home
  21. 21. Case カピバラさん 背景 社内の各システム毎にID情報が分散 既存のLDAPサーバがあった 既存の構造的には認証統一には難しかった 新規にLDAP作成 管理アプリ作成 管理 ユーザ一覧/検索/新規作成/所属変更 パスワード初期化 等 ユーザ パスワード変更
  22. 22. Case カピバラさん パスワード初期化 ユーザ管理 パスワード変更 一覧 検索 新規作成 所属変更
  23. 23. Case カピバラさん ruby-ldap ActiveLdap は使いづらかったそうで回避(泣 確かに ruby-ldap の方がプリミティブな実装 ruby-ldapに限らず、LDAPについても情報が 不足して困った 速度面・利便性について特に不満なし
  24. 24. Case 2 事例提供者:岡澤さん http://d.hatena.ne.jp/yujiorama/
  25. 25. Case 岡澤さん ruby-ldap を利用 分散した社員マスタ/認証を統合 アカウント 作成・編集・削除 パスワード変更など ML 依頼があり次第 管理作業 参照できる 作成・変更 request
  26. 26. Case 岡澤さん ruby-ldap 元々作った人が「Rails 関連は面倒」(笑 openldap のコマンドとほぼ同じような作り で、コマンドの使い方が判ると直観的に使え た 同様の理由で、デバッグ等もやりやすかった
  27. 27. Case 3 事例提供者:谷口さん
  28. 28. Case 4 事例提供者:高瀬
  29. 29. Case 高瀬 activeldap アカウント/権限管理 sync batch ユーザ管理 batch (Create folder 有効化/編集/権限付与 (script/runner) & ACL settings) 退職処理 パスワード初期化など Password 共有フォルダ管理 Warning(mail) サブシステム権限管理 共有フォルダ etc 作成 権限編集 サブシステム権限編集 request パスワード変更
  30. 30. Case 高瀬 activeldap Rails の機能を活用したかった script/runner でライブラリ使えるの便利 validation や association 使えるの便利 validationは作りによってはとっても遅くなる uid の uinique チェックのため検索するなどのvalidation を多数含めたりすると 検索時に取得する属性の数を少なくして速くする等の工夫 をすると吉 テストも Rails に統合 VM でdevelopment, test 用の LDAP を作成 環境(development, test)によって接続先 LDAP 切替 Rspec でふつうにテスト
  31. 31. Code Examples
  32. 32. Code Examples – ruby-ldap (1) Connection and Bind LDAP::Conn.new / LDAP::Conn#bind @conn = LDAP::Conn.new('localhost', 389) @conn.bind("cn=Manager,o=RubyKaigi2010,c=jp", pass) # => #<LDAP::Conn:0xb7f0d400> LDAP::Conn.new で接続 SSL接続には LDAP::SSLCon.new を利用 LDAP::Conn#bind でバインドする 第三引数の定数で認証方式の指定 Default: LDAP_AUTH_SIMPLE grep LDAP_AUTH ldap.c SSL 接続には LDAP::SSLConn
  33. 33. Code Examples – ruby-ldap (2) search LDAP::Conn#search @conn.search("o=RubyKaigi2010,c=jp", LDAP::LDAP_SCOPE_SUBTREE, "(objectclass=*)") do |entry| entry # => #<LDAP::Entry:…>, #<LDAP::Entry:…>, … end 検索結果を LDAP ::Entry で返す ブロック必須 他にも結果を Hash で返す search2 がある Search2 はブロック無しで検索可能
  34. 34. Code Examples – ruby-ldap (3) Add LDAP::Conn#add entry = {"objectclass" => ["top", "person"], "cn" => ["Ruby Taro"], "sn" => ["Ruby", "Taro"]} # 追加先のDN を指定し、属性の内容を渡す @conn.add("cn=#{entry['cn'][0]},o=RubyKaigi2010,c=jp", entry) # => #<LDAP::Conn:0xXXXXXXXX> HashやLDAP::MOD_ADD でエントリ追加 上記の例は Hash の場合
  35. 35. Code Examples – ruby-ldap (4) Modify LDAP::Conn#modify mod_hash = {"sn" => ["hoge", "taro"]} @conn.modify("cn=Ruby Taro,o=RubyKaigi2010,c=jp", mod_hash) # => #<LDAP::Conn:0xb7f0bbc8> HashやLDAP::MOD_MOD でエントリ更新 上記の例は Hash の場合
  36. 36. Code Examples – ruby-ldap (5) Gathering Error Information LDAP::Error begin @conn.delete("cn=Ruby Taro,o=RubyKaigi2010,c=jp") rescue => e e # => #<LDAP::ResultError: No such object> e.message # => "No such object“ @conn.err # => 32 @conn.err2string(@conn.err) # => "No such object" end 原則として LDAP::Error が投げられる様子 Human Readable なメッセージは LDAP::Error 自身が持っている エラーコードが欲しい場合に #<LDAP::Conn> に問い合わせる
  37. 37. Code Examples – net-ldap(1) Connection and BIND Net::LDAP.new @ldap = Net::LDAP.new :host => 'localhost', :port => 389, :base => 'o=RubyKaigi2010,c=jp', :auth => { :method => :simple, :username => 'cn=Manager,o=RubyKaigi2010,c=jp', :password => password } @ldap # => #<Net::LDAP:0xb7e086f4 @base="o=RubyKaigi2010,c=jp",…> 接続と bind を一緒に行うのが通例
  38. 38. Code Examples – net-ldap(2) search Net::LDAP#search @ldap.search # => [#<Net::LDAP::Entry: ...>, #<Net::LDAP::Entry ...>] @ldap.search(:filter => Net::LDAP::Filter.eq('uid', 'matz')) # => [#<Net::LDAP::Entry: … :uid=>["matz"], …>] デフォルトでは “(objectClass=*)” で検索 フィルタを利用する場合は Net::LDAP::Filter を利用して フィルタを構成する ブロックを渡してイテレーションさせることも可
  39. 39. Code Examples – net-ldap(3) Add Net::LDAP#add attrs = { :objectclass => ["top", "inetOrgPerson", "posixAccount"], :cn => "ruby taro", :gidNumber => "1999", :homeDirectory => "/home/ruby_taro", :sn => ["ruby", "taro"], :uid => "ruby_taro", :uidNumber => "1999" } dn = "uid=#{attrs[:uid]},ou=Users,o=RubyKaigi2010,c=jp" @ldap.add(:dn => dn, :attributes => attrs) # => false @ldap.get_operation_result # => #<OpenStruct … "Success",…, code=0> ※何故か false を返してますが成功しています (僕の環境のせい?)
  40. 40. Code Examples – net-ldap(4) Modify Net::LDAP#modify dn = "uid=ruby_taro,ou=Users,o=RubyKaigi2010,c=jp" opts = [ [:add, :mail, "hoge@example.com"], [:replace, :sn, ["hoge", "fuga"]], [:delete, :telephoneNumber] ] @ldap.modify(:dn => dn, :operations => opts) # => false ※これも何故か false を返してますが成功しています (僕の環境のry)
  41. 41. Code Examples – net-ldap(5) Gathering Error Information Net::LDAP#get_operation_result @ldap.add(:dn => dn, :attr => attr) # => false @ldap.get_operation_result.code # => 2 @ldap.get_operation_result.message # => "Protocol Error" @ldap.get_operation_result.error_message # => "no attributes provided" @ldap.get_operation_result.matched_dn # => "" @ldap.get_operation_result # => #<OpenStruct …> OpenStruct でエラー情報を返す 上記は objectClass の MUST の属性を設定していない場合の例
  42. 42. Code Examples – activeldap(1) Connection and Bind ActiveLdap::Base.setup_connection ActiveLdap::Base.setup_connection :base => "o=RubyKaigi2010,c=jp", :bind_dn => "cn=Manager,o=RubyKaigi2010,c=jp", :password_block => lambda{pass}, :logger => logger この時点では接続が確立されず、何か操作した時に接続 サブクラス毎に接続先を変えること等も可能
  43. 43. Code Examples – activeldap(2) Mapping define subclass class User < ActiveLdap::Base ldap_mapping :prefix => "ou=Users", :classes => %w(person), :scope => :sub, :dn_attribute => "uid" end クラスを任意のツリーにマッピング このクラスを利用して指定したツリー以下の検索等を行う インスタンスを作成するとエントリにマッピングされる belongs_to, has_many 等も利用できる 全体的に ActiveRecord と類似したインターフェース
  44. 44. Code Examples – activeldap(3) Search ActiveLdap::Base.find User.find(:all) # => [#<User ...>, #<User ...>, ...] User.find(:first, :filter => “(cn=Ruby Taro)”) #=> #<User ...> ActiveRecord と同様の検索方法 検索条件は :filter オプション エントリとマッピング済みのインスタンスを返す
  45. 45. Code Examples – activeldap(4) Add/Modify ActiveLdap::Base#save , save! user = User.new :sn => 'Ruby', :cn => "Ruby Taro" user.save # => true user.sn = “Hoge” user.save # => true インスタンスの状態に合わせて add/modify 新規オブジェクトなら add 既存オブジェクトなら modify 属性に複数の値を入れたい場合は配列で
  46. 46. Code Examples – activeldap(5) Gathering Error Information ActiveRecord::Validations#errors user = User.new :sn => 'Ruby', :cn => "Ruby Taro" user.save # => false user.errors # => #<ActiveRecord::Errors ...> user.errors.full_messages # => ["distinguishedName is duplicated: cn=Ruby Taro,ou=Users,o=RubyKaigi2010,c=jp"] errors メソッドが ActiveRecord::Errors を返す Rails で Webインターフェース等作る際は比較的楽
  47. 47. 参考資料
  48. 48. 参考資料 LDAP RFC 4510 http://datatracker.ietf.org/doc/rfc4510/ Rubyist Magazine - ActiveLdap を使ってみよう(前編)- LDAPとは http://jp.rubyist.net/magazine/?0027-ActiveLdap#l4 ruby-ldap Ruby/LDAP (Homepage) http://ruby-ldap.sourceforge.net/ RDoc http://ruby-ldap.sourceforge.net/rdoc/ ソースコード。特に test ディレクトリ以下 net-ldap Net-ldap-0.1.1 Documentation (Homepage) http://net-ldap.rubyforge.org/ activeldap ActiveLdap を使ってみよう(前編) http://jp.rubyist.net/magazine/?0027-ActiveLdap ActiveLdap を使ってみよう(後編) http://jp.rubyist.net/magazine/?0029-ActiveLdap Rails で作る ActiveDirectory と連携した社内システム http://www.clear-code.com/archives/rails-seminar-technical-night/ ActiveLdap 日本語チュートリアル http://code.google.com/p/ruby-activeldap/wiki/TutorialJa
  49. 49. ありがとうございました Thank you.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×