Python 和 LDAP

来源:互联网 发布:童年 知乎 编辑:程序博客网 时间:2024/06/05 15:21

Python 和 LDAP

用 Python-LDAP 执行 LDAP 的 CRUD(创建、读取、更新和删除)操作:

Noah Gift, 软件工程师, Giftcs
Grig Gheorghiu, 技术主管, RIS Technology

简介: 大多数系统管理员在职业生涯中都会遇到需要与 LDAP 服务器交互的情况。本文讲解如何使用 LDAP 实现 Apache 身份验证,以及如何使用 Python 模块 python-ldap 在 OpenLDAP 数据库上执行 CRUD(即创建、读取、更新和删除)操作。

本文的标签:  ldap, python

标记本文!

发布日期: 2009 年 1 月 05 日
级别: 中级 其他语言版本: 英文
访问情况 : 3001 次浏览
评论: 0 (查看 | 添加评论 - 登录)

平均分 3 星 共 5 个评分 平均分 (5个评分)
为本文评分

简介

在本文中,作者将讲解如何在 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。

我衷心感谢 David Goodger 帮助审阅了本文!


原创粉丝点击