Ruby で扱う LDAP のススメ

  • 13,909 views
Uploaded on

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

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • RubyKaigi2010 企画 ”Ruby で扱う LDAP のススメ”資料です。

    数例ある事例紹介の内、谷口さんの事例紹介のスライドは以下にあります
    http://www.slideshare.net/tasheeen/active-ldap
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
13,909
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
43
Comments
1
Likes
6

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Ruby で扱う LDAP のススメ - Ruby meets LDAP - その選択肢と事例 - Choices and cases – 高瀬一彰 / @tasheeen
  • 2. Who? 高瀬一彰 (Kazuaki Takase) エイケア・システムズ株式会社 Lang: perl→php→ruby+javascript Rails で LDAP 管理アプリ
  • 3. Why? Ruby with LDAP に関する情報の不足 LDAP 自体がマイナー Ruby コミュニティに、LDAPを扱うため の入り口となる情報を提供したい LDAPって? どんなライブラリがあるの? どれを使えばいいの?
  • 4. What? LDAP の概略 LDAP ライブラリの紹介 事例紹介 コード例 参考資料一覧
  • 5. LDAPの概略
  • 6. LDAPの概略(1) Keywords LDAP Entry ObjectClass Attribute DIT Distinguished Name
  • 7. LDAPの概略(2) Lightweight Directory Access Protocol RFC4510などで定義 元々は DAP。その軽量版(=Lightweight) Directory = 台帳・名簿 何でも登録可能 台帳として最適化したデータ構造を持つ
  • 8. LDAPの概略(3) Entry LDAPにおけるデータの基本単位 =台帳の登録単位。名簿なら「人」 ≒RDBにおける行に近い 現実世界の「物(=オブジェクト)」を表す エントリは属性を持つ 「人」に対する「名前」「電話番号」etc. RDB と違う点 エントリがスキーマを持つ
  • 9. LDAPの概略(4) Object Class エントリが「何」か OOP の「クラス」と同義 オブジェクトクラスに よって持てる属性が変わる Unix アカウントのエント リなら posixAccount 継承・抽象型・構造型・補 助型などの概念とルール posixAccountは補助型 person 等と組み合わせる
  • 10. LDAPの概略(5) Attributes 一つの属性に複数の値 を持っている場合が多 い 台帳・名簿としての 考え方
  • 11. LDAPの概略(6) Directory Information Tree (DIT) ディレクトリデータベースを DIB ツリー構造していると DIT 階層的に管理するのがコンセプト エントリがツリーとして連なる
  • 12. LDAPの概略(7) Distinguished Name(DN) Rlative Distinguished Name(RDN) その階層における一意の 名前 cn=Ruby Taro エントリが持つ任意の属 性がRDNになる RDNを下から一番上まで cn=Ruby Taro,o=RubyKaigi2010,c=jp 繋げるとツリーで一意に 特定される名前になる (DN)
  • 13. Ruby with LDAP
  • 14. Ruby with LDAP - libs Obsolete ! Obsolete !
  • 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. Ruby with LDAP – ruby-ldap ruby-ldap RFC1823 (The LDAP Application Programming Interface) のRuby版実装 使い方は同梱のテストが参考になる 速い! bind search add modify C Extension etc…
  • 17. Ruby with LDAP – net-ldap net-ldap Pure Ruby な LDAP API 実装 ポータビリティに富む RDoc のドキュメントが結構しっかりしている bind search add modify Pure Ruby etc…
  • 18. Ruby with LDAP - activeldap activeldap ActiveRecord を参考に作られた、LDAP API ruby-ldap や net-ldap, JNDI を内部的に利用 クラスはツリーを抽象、インスタンスはエントリを抽象 ActiveLdap::Base find User new (Subclass) cn= save destroy
  • 19. Cases
  • 20. Case 1 事例提供者:カピバラさん http://sites.google.com/site/capibaraproject/home
  • 21. Case カピバラさん 背景 社内の各システム毎にID情報が分散 既存のLDAPサーバがあった 既存の構造的には認証統一には難しかった 新規にLDAP作成 管理アプリ作成 管理 ユーザ一覧/検索/新規作成/所属変更 パスワード初期化 等 ユーザ パスワード変更
  • 22. Case カピバラさん パスワード初期化 ユーザ管理 パスワード変更 一覧 検索 新規作成 所属変更
  • 23. Case カピバラさん ruby-ldap ActiveLdap は使いづらかったそうで回避(泣 確かに ruby-ldap の方がプリミティブな実装 ruby-ldapに限らず、LDAPについても情報が 不足して困った 速度面・利便性について特に不満なし
  • 24. Case 2 事例提供者:岡澤さん http://d.hatena.ne.jp/yujiorama/
  • 25. Case 岡澤さん ruby-ldap を利用 分散した社員マスタ/認証を統合 アカウント 作成・編集・削除 パスワード変更など ML 依頼があり次第 管理作業 参照できる 作成・変更 request
  • 26. Case 岡澤さん ruby-ldap 元々作った人が「Rails 関連は面倒」(笑 openldap のコマンドとほぼ同じような作り で、コマンドの使い方が判ると直観的に使え た 同様の理由で、デバッグ等もやりやすかった
  • 27. Case 3 事例提供者:谷口さん
  • 28. Case 4 事例提供者:高瀬
  • 29. Case 高瀬 activeldap アカウント/権限管理 sync batch ユーザ管理 batch (Create folder 有効化/編集/権限付与 (script/runner) & ACL settings) 退職処理 パスワード初期化など Password 共有フォルダ管理 Warning(mail) サブシステム権限管理 共有フォルダ etc 作成 権限編集 サブシステム権限編集 request パスワード変更
  • 30. Case 高瀬 activeldap Rails の機能を活用したかった script/runner でライブラリ使えるの便利 validation や association 使えるの便利 validationは作りによってはとっても遅くなる uid の uinique チェックのため検索するなどのvalidation を多数含めたりすると 検索時に取得する属性の数を少なくして速くする等の工夫 をすると吉 テストも Rails に統合 VM でdevelopment, test 用の LDAP を作成 環境(development, test)によって接続先 LDAP 切替 Rspec でふつうにテスト
  • 31. Code Examples
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Code Examples – activeldap(3) Search ActiveLdap::Base.find User.find(:all) # => [#<User ...>, #<User ...>, ...] User.find(:first, :filter => “(cn=Ruby Taro)”) #=> #<User ...> ActiveRecord と同様の検索方法 検索条件は :filter オプション エントリとマッピング済みのインスタンスを返す
  • 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. 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. 参考資料
  • 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. ありがとうございました Thank you.