歡迎您光臨本站 註冊首頁

Python 和 LDAP

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
大多數系統管理員在職業生涯中都會遇到需要與 LDAP 伺服器交互的情況。本文講解如何使用 LDAP 實現 Apache 身份驗證,以及如何使用 Python 模塊 python-ldap 在 OpenLDAP 資料庫上執行 CRUD(即創建、讀取、更新和刪除)操作。

簡介

在本文中,作者將講解如何在 Amazon EC2 虛擬機上安裝 OpenLDAP 的實例,設置 Apache/LDAP 身份驗證,然後使用 Python 執行 CRUD(即創建、讀取、更新和刪除)操作。一定要注意,可以在 Fedora、Ubuntu、Red Hat、AIX® 等操作系統上安裝 LDAP。但是在本文中,我們決定採用 Amazon EC2 虛擬機。您可以在任何 Linux® 發行版或手邊的任何環境中進行實踐。最後,我們將在本文中討論許多代碼和複雜的技術。您應該首先下載 示例代碼,供閱讀本文時參考。

通過程序控制 LDAP 常常是系統管理員的工作,所以 Python 中存在一個用來操作 LDAP 的庫就不奇怪了。python-ldap 模塊已經存在了一段時間了,在 參考資料 一節中可以找到官方文檔的鏈接。

我們假設您熟悉一般的 LDAP 概念,比如目錄模式、Distinguished Names (DN)、Common Names (CN)、過濾器和屬性。本文不是 LDAP 教程;我們不喜歡大談理論,而是主要關注使用和管理 LDAP 資料庫的實際示例。

什麼是 LDAP 以及它的用途是什麼?

那麼,究竟什麼是 LDAP 呢?按照嚴格的定義,LDAP 代表 Lightweight Directory Access Protocol。但是,這個名稱已經成了一種目錄體系結構的同義詞。當人們提到 LDAP 時,常常不是指協議,而是指目錄服務。

LDAP 的最新版本是 V3。LDAP 被設計成一種通用目錄,但是有幾個約定。一個記錄由一個 DN 和一個或多個屬性組成,屬性是在屬性定義中定義的。LDAP 資料庫的模式與典型的關係資料庫模式定義語言很不一樣。例如,典型的關係資料庫是基於表的,而 LDAP 結合了繼承。如果希望進一步了解 LDAP 理論,我們強烈建議您閱讀 參考資料 中列出的 OpenLDAP 圖書。

那麼,LDAP 的用途是什麼?它用於對構建 IT 基礎結構的人進行身份驗證。它還能夠與 Samba 很好地配合,所以有經驗的系統管理員可以以零成本設置非常高級的 IT 基礎結構,而不必承擔其他專有目錄解決方案的成本。“身份驗證” 意味著,基礎結構中的所有計算機只需與 LDAP 目錄伺服器通信,即可使用相同的用戶名和密碼。

LDAP 的初始設置和填充

如果希望按照本文的說明設置 LDAP,那麼需要一個 Fedora Core 8 實例。我們使用一個運行 Fedora Core 8 32-bit 的 Amazon EC2 虛擬機實例。可以在物理伺服器上安裝 LDAP,也可以使用您選擇的技術在虛擬機上安裝。注意,對於所有示例,我們使用一個稱為 unisonis.com 的域,但是有一份 RFC 建議使用 example.com。

步驟 1:使用 yum 安裝 openldap 包:

                  [root@domU ]# yum install openldap  openldap-devel            openldap-servers openldap-clients                     [root@domU ]# yum list installed | grep openldap           openldap.i386           2.3.39-4.fc8   installed                  openldap-clients.i386   2.3.39-4.fc8   installed                  openldap-devel.i386     2.3.39-4.fc8   installed                  openldap-servers.i386   2.3.39-4.fc8   installed                

步驟 2:設置管理員密碼(我們將把 SSHA 散列值粘貼在 slapd.conf 中)。注意,slapd 代表 Standalone LDAP 服務,所以此服務控制 LDAP 本身:

                [root@domU ]# slappasswd           New password:            Re-enter new password:                   

步驟 3:編輯 slapd.conf 配置文件並添加一般 LDAP 安裝所需的條目,比如根 DN 和根/管理員密碼:

               [root@domU ]# vi /etc/openldap/slapd.conf           #Add entries:          database bdb         suffix "dc=unisonis,dc=com"         rootdn "cn=Manager,dc=unisonis,dc=com"         rootpw {SSHA}pasted_from_slappasswd_output        directory /var/lib/ldap                  

步驟 4:啟動 LDAP 服務:

                  [root@domU ]# service ldap start           Starting slapd:                                            [  OK  ]                    

步驟 5:運行 LDAP 並搜索 'namingContexts' 屬性,從而測試 LDAP:

                 [root@domU ]# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts           # extended LDIF           #           # LDAPv3           # base <> with scope baseObject           # filter: (objectclass=*)           # requesting: namingContexts            #              #           dn:           namingContexts: dc=unisonis,dc=com              # search result           search: 2           result: 0 Success              # numResponses: 2           # numEntries: 1                  

步驟 6:使用 ldapadd 和 LDIF 文件在 LDAP 資料庫中添加更多條目。注意,LDIF 代表 LDAP Data Interchange Format,這是用於對 LDAP 資料庫進行大量更新的數據格式:

                    [root@domU ]# cat unisonis.ldif              dn: dc=unisonis,dc=com             objectclass: dcObject             objectclass: organization             o: Example Company             dc: unisonis                         dn: cn=Manager,dc=unisonis,dc=com             objectclass: organizationalRole             cn: Manager                          [root@domU ]# ldapadd -x -D "cn=Manager,dc=unisonis,dc=com" -W -f   unisonis.ldif              Enter LDAP Password:              adding new entry "dc=unisonis,dc=com"                adding new entry "cn=Manager,dc=unisonis,dc=com"                      

步驟 7:下一步是用示例條目填充 LDAP 目錄。我們使用三個小丑的信息(靈感來源於 LDAP 文章 http://www.yolinux.com/TUTORIALS/LinuxTutorialLDAP.html):

                      [root@domU ]# cat stooges.ldif; # to conserve space, we show the LDAP data for   only one of the three stooges          dn: ou=MemberGroupA,dc=unisonis,dc=com           ou: MemberGroupA           objectClass: top           objectClass: organizationalUnit           description: Members of MemberGroupA                      dn: ou=MemberGroupB,dc=unisonis,dc=com           ou: MemberGroupB           objectClass: top           objectClass: organizationalUnit           description: Members of MemberGroupB                      dn: cn=Larry Fine,ou=MemberGroupA,dc=unisonis,dc=com           ou: MemberGroupA           o: stooges           cn: Larry Fine           objectClass: top           objectClass: person           objectClass: organizationalPerson           objectClass: inetOrgPerson           mail: LFine@unisonis.com           givenname: Larry           sn: Fine           uid: larry           homePostalAddress: 15 Cherry Ln. Plano TX 78888           postalAddress: 215 Fitzhugh Ave.           l: Dallas           st: TX           postalcode: 75226           telephoneNumber: (800)555-1212           homePhone: 800-555-1313           facsimileTelephoneNumber: 800-555-1414           userPassword: larrysecret           title: Account Executive           destinationindicator: /bios/images/lfine.jpg                     [root@domU ]# ldapadd -x -D "cn=Manager,dc=unisonis,dc=com" -W -f stooges.ldif                  

如果願意,現在就可以對剛才創建的 LDAP 資料庫做各種搜索。下面的示例搜索與 'stooges' 組織相關的所有 LDAP 條目:

      [root@domU conf.d]# ldapsearch -x -b 'dc=unisonis,dc=com' '(o=stooges)'         

在下一節中,我們討論如何通過配置 Apache 實現 LDAP 身份驗證,然後討論 Python 和 LDAP。





設置 Apache LDAP 身份驗證

LDAP 最常見的用途之一是為 Web 服務等提供身份驗證數據。在本節中,我們使用前面預先填充的 LDAP 資料庫控制對一個 Apache 虛擬主機的訪問。

首先,需要為使用 LDAP 身份驗證的虛擬主機創建一個 Apache 配置文件。對於試圖登錄的用戶,要求提供有效的電子郵件地址和密碼。配置文件如下所示:

                    [root@domU ]# cat /etc/httpd/conf.d/unisonis.conf              <VirtualHost *:80>             ServerName www.unisonis.com             DocumentRoot "/ebs1/www/unisonis"             <Directory "/ebs1/www/unisonis">                 AuthType Basic                 AuthName "unisonis.com: please login with email address"                 AuthBasicProvider ldap                 AuthLDAPURL ldap://localhost:389/dc=unisonis,dc=com?mail?sub?(o=stooges)                 require valid-user                 Order Allow,Deny                 Allow from all                 Options Indexes FollowSymLinks                 AllowOverride None             </Directory>            </VirtualHost>                      

通過 mod_auth_ldap 模塊向 Apache 提供 LDAP 身份驗證,此模塊是在 Fedora Core 8 httpd 包中默認安裝的。對於試圖登錄的用戶,要求在 'stooges' 組織中包含有效的電子郵件地址和密碼,這樣才能訪問上面定義的 Apache 虛擬主機。請注意 AuthLDAPURL 指令,它指定通過 LDAP 伺服器實現用戶身份驗證所用的查詢。我們搜索 'mail' 屬性並應用過濾器 (o=stooges)。AuthLDAPURL 指令的完整語法請參見 http://httpd.apache.org/docs/2.0/mod/mod_auth_ldap.html#authldapurl。

關於在 Apache 上配置 LDAP 的更多信息請參見 參考資料。





用 Python-LDAP 執行 CRUD 操作

現在,準備使用 Python 與 LDAP 交互。為此,必須安裝 python-ldap 模塊。在 參考資料 中,可以找到關於安裝此模塊的詳細信息的鏈接。實際上,只需要執行 “easy install”。首先下載 easy_install 腳本:

       http://peak.telecommunity.com/dist/ez_setup.py          

然後輸入:

          sudo easy_install python-ldap          

注意,根據操作系統的不同,此包依賴的一些軟體略有差異。如果在安裝此包時遇到問題,請仔細閱讀安裝說明。

安裝 python-ldap 之後,就可以執行 CRUD 操作了。下面編寫一個執行這些操作的類。


Python LDAP CRUD 類
       #!/bin/env python                import sys, ldap                LDAP_HOST = 'localhost'        LDAP_BASE_DN = 'dc=unisonis,dc=com'        MGR_CRED = 'cn=Manager,dc=unisonis,dc=com'        MGR_PASSWD = 'mypasswd'        STOOGE_FILTER = 'o=stooges'                class StoogeLDAPMgmt:                    def __init__(self, ldap_host=None, ldap_base_dn=None, mgr_cred=None,   mgr_passwd=None):                if not ldap_host:                    ldap_host = LDAP_HOST                if not ldap_base_dn:                    ldap_base_dn = LDAP_BASE_DN                if not mgr_cred:                    mgr_cred = MGR_CRED                if not mgr_passwd:                    mgr_passwd = MGR_PASSWD                self.ldapconn = ldap.open(ldap_host)                self.ldapconn.simple_bind(mgr_cred, mgr_passwd)                self.ldap_base_dn = ldap_base_dn                    def list_stooges(self, stooge_filter=None, attrib=None):                if not stooge_filter:                    stooge_filter = STOOGE_FILTER                s = self.ldapconn.search_s(self.ldap_base_dn, ldap.SCOPE_SUBTREE,   stooge_filter, attrib)                print "Here is the complete list of stooges:"                stooge_list = []                for stooge in s:                    attrib_dict = stooge[1]                    for a in attrib:                        out = "%s: %s" % (a, attrib_dict[a])                        print out                        stooge_list.append(out)                return stooge_list                    def add_stooge(self, stooge_name, stooge_ou, stooge_info):                stooge_dn = 'cn=%s,ou=%s,%s' % (stooge_name, stooge_ou, self.ldap_base_dn)                stooge_attrib = [(k, v) for (k, v) in stooge_info.items()]                print "Adding stooge %s with ou=%s" % (stooge_name, stooge_ou)                self.ldapconn.add_s(stooge_dn, stooge_attrib)                        def modify_stooge(self, stooge_name, stooge_ou, stooge_attrib):                stooge_dn = 'cn=%s,ou=%s,%s' % (stooge_name, stooge_ou, self.ldap_base_dn)                print "Modifying stooge %s with ou=%s" % (stooge_name, stooge_ou)                self.ldapconn.modify_s(stooge_dn, stooge_attrib)                        def delete_stooge(self, stooge_name, stooge_ou):                stooge_dn = 'cn=%s,ou=%s,%s' % (stooge_name, stooge_ou, self.ldap_base_dn)                print "Deleting stooge %s with ou=%s" % (stooge_name, stooge_ou)                self.ldapconn.delete_s(stooge_dn)          

此類中的方法名就能夠說明方法的作用,所以我們只討論在實現這個類時的一些步驟。如果您已經按照前面的步驟填充了 LDAP 資料庫,現在還應該下載代碼示例。

首先,創建此類的實例:

      l = StoogeLDAPMgmt()        

然後就可以執行 CRUD 了。

接下來,用 Python 代碼添加一些功能。應該複製並粘貼下載的源代碼,因為手工輸入容易出錯。下面是 CRUD 中的 “C”(創建):


LDAP 創建
          # add new stooge: Harry Potter            stooge_name = 'Harry Potter'            stooge_ou = 'MemberGroupB'            stooge_info = {'cn': ['Harry Potter'], 'objectClass': ['top', 'person',   'organizationalPerson', 'inetOrgPerson'],                  'uid': ['harry'], 'title': ['QA Engineer'], 'facsimileTelephoneNumber':   ['800-555-3318'], 'userPassword': ['harrysecret'],                  'postalCode': ['75206'], 'mail': ['HPotter@unisonis.com'],   'postalAddress':  ['2908 Greenville Ave.'],                  'homePostalAddress': ['14 Cherry Ln. Plano TX 78888'], 'pager':   ['800-555-1319'], 'homePhone': ['800-555-7777'],                  'telephoneNumber': ['(800)555-1214'], 'givenName': ['Harry'], 'mobile':   ['800-555-1318'], 'l': ['Dallas'],                  'o': ['stooges'], 'st': ['TX'], 'sn': ['Potter'], 'ou': ['MemberGroupB'],   'destinationIndicator': ['/bios/images/hpotter.jpg'], }            try:                l.add_stooge(stooge_name, stooge_ou, stooge_info)                   except ldap.LDAPError, error:                print 'problem with ldap',error          

現在對此條目執行 “R”(讀取):


LDAP 讀取
       # see if it was added         l.list_stooges(attrib=['cn', 'mail', 'homePhone'])         

現在更新此條目,即執行 “U”:


LDAP 更新
        # now modify home phone          stooge_modified_attrib = [(ldap.MOD_REPLACE, 'homePhone', '800-555-8888')]          try:              l.modify_stooge(stooge_name, stooge_ou, stooge_modified_attrib)          except ldap.LDAPError, error:              print 'problem with ldap',error        

最後,執行 “D”(刪除):


LDAP 刪除
       # now delete Harry Potter         try:             l.delete_stooge(stooge_name, stooge_ou)         except ldap.LDAPError, error:             print 'problem with ldap',error         





結束語

本文簡要介紹了在 Amazon EC2 Fedora 實例上安裝 OpenLDAP 的過程,我們用測試數據填充了 LDAP 資料庫,簡要討論了從命令行與 LDAP 資料庫交互,演示了如何通過配置 Apache 實現 LDAP 身份驗證。最後,通過 Python 代碼控制 LDAP。Python 示例最出色的優點之一是,與腳本(比如 bash 腳本)代碼相比,Python 代碼看起來舒服得多。Python 代碼因其簡潔和可讀性強而聞名,這在處理 LDAP 編程等複雜操作時表現尤為突出。

我們實際上沒有研究 LDAP 和 Python 的實際示例,但是介紹了如何使用 API 執行 CRUD 操作。使用 python-ldap 庫是一種很實用的想法。在每次創建 TRAC 新實例時,您可能希望用 LDAP 組中的所有用戶填充不同的 TRAC 項目管理網站。這很容易用我們討論的技術實現:查詢 LDAP 組,在 TRAC 中為每個組成員插入許可。還有許多其他操作 LDAP 的實用方法,希望本文能幫助您如何在自己的項目中進一步利用 LDAP。(責任編輯:A6)



[火星人 ] Python 和 LDAP已經有863次圍觀

http://coctec.com/docs/linux/show-post-69007.html