使用 OpenLDAP 提供集中式网络目录服务

来源:互联网 发布:ug nx 8.0编程电子书 编辑:程序博客网 时间:2024/05/16 17:57

http://minitrue.googlecode.com/svn-history/r112/trunk/txt/ch12.txt


第 12 章 使用 OpenLDAP 提供集中式网络目录服务
 
12.0 介绍 
 
我相信,知道如何管理一个轻量级目录访问协议(LDAP)目录服务器,已成为网络管理员的必备技能。LDAP 目录是使网络保持简单的关键所在。它是你的全局跨平台跨应用目录,支持简化的网络验证,以及集中的公司数据存储。LDAP 是跨平台、网络自适应和基于标准的协议。现在已有大量 LDAP 实现,在本章中,我们将使用优秀的免费自由软件 OpenLDAP。
 
LDAP 被众多应用程序广泛支持,例如,大多数电子邮件客户端都带有 LDAP 客户端。另外,多数数据库、内容管理系统(CMS)、群件和消息服务器、验证服务器、客户管理应用和应用服务器都能与 LDAP 服务器对话。
 
某些人喜欢争论 LDAP 是不是数据库。严格来说,这是一种协议,而不是数据库。它访问的是一种为高速读取进行特别优化的数据库。可以将它用于相对静态的信息,比如公司目录、用户数据、客户数据、密码、资产追踪和密钥等。OpenLDAP 使用 Sleepycat Berkeley DB。
 
为什么不用一个普通的关系数据库,比如 PostgreSQL、Oracle 或者 MySQL 呢?如果你喜欢的话当然可以,但是你会失去 LDAP 所带来的好处,也就是:
 
 • 高速读取
 • 灵活的数据类型
 • 几近通用的应用支持
 • 细化数据访问控制
 • 分布式存储和复制
 • 无需数据库专家级管理员
 • 无需定制 API
 
你不应该将 OpenLDAP 作为网店或者网站的后端,比如,不能用于任何需要快速频繁变更的应用程序。那里才要用到关系型数据库管理系统(RDBMS)。
 
Sleepycat BDB 与关系数据库的结构有所不同。不像关系数据库,以栏目和行的形式存储信息,而且有一个严格的索引和字段集合,这里的数据是以属性类型/属性值配对形式存储的。这样的结构在设计数据形式时提供了极大的灵活性。以某种特殊的用户记录为例,可以添加新的数据类型,而无须重新设计整个数据库。你可以存储任何种类的文本或二进制数据。因为这就像一个大的普通文件一样简单,添加新条目也非常方便——只要把它们附加上去即可。OpenLDAP 支持分布式的架构、复制和加密。
 
 
LDAP 目录结构
 
让我们回顾一下 LDAP 目录的基本概念和结构。这比拥有关于配置选项的广博知识更为重要,因为如果你对于自己需要什么,以及各个部分相互之间的联系没有清晰的概念,那么 LDAP 就是一团神秘的迷雾。但其实它并没有那么神秘,一旦你掌握了基本概念,那么就能很快进入状态。正如教练们经常说的,首先得打好基础。LDAP 目录可以画成一张标准的自顶向下树状结构图,根位于顶部,而分支逐级向下延展。图 12-1 是一个层级命名空间,它也被称为目录信息树(DIT)。
 
{{附图}}
图 12-1。一个 LDAP 层级样例。
 
这个目录样例的根是 country 条目。下一站是 state 条目,然后是 organizational unit(OU)条目,也就是公司名称。从这里分为两个不同的公司条目,因此也被称为 organizational units。左边的分支以用户 ID(UID)终结。质量保证(QA)OU 可以容纳多个用户,而不仅是样例中的一个。
 
现在要说到重点了:Terry Jones 有一个 Distinguished Name(DN),由 Terry 的 Relative Distinguished Name(RDN)组成,在这个例子中就是 UID,还要加上所有上级条目:uid=terryjones, ou=qa, ou=alrac's cookies, ou=or, c=us。任何属性都可以是 RDN,它必须在所属等级的众多条目中保持唯一。UID 通常是唯一的,因为它是用户登录的基本要素,但是你也可以使用其它任何属性。显然,这里需要一点小常识,例如,有很多重复的姓氏,那么使用 SN 属性就会导致问题。最常用于标识人的 RDN 是 UID 或 Common Name(CN)。
 
目录的基本单元是条目(entry)。条目也被成为记录(record)或目录对象(directory object)。Terry Jones 的条目包含了大量属性(attribute),诸如姓名、电话号码、email 地址,等等。你不能凭空杜撰属性,它们必须是在 OpenLDAP 中已经定义的。一种查看它们的方便途径是使用 GQ LDAP 客户端(http://sourceforge.net/projects/gqclient/)。你也可以在 /etc/ldap/schema(Fedora 上是 /etc/openldap/schema)目录文件中看到 objectClass 的定义。
 
你可以创建自己的 objectClass 定义和属性类型。我不建议这样做,除非你一定需要那些没有被包括进去的东西。默认的 schema 是可扩展的,而且已经有人为了将它们通用化而付出了巨大努力,没有必要重新发明轮子。另一方面(总会有另外一面,不是吗),这样可以使 OpenLDAP 变得更为灵活、更容易扩展,而且可以很方便地共享定制的 schema。
 
每个属性都是由属性类型和属性值组成的。属性可以有多个值,例如,Terry Jones 的条目可能会是这样:
 
    uid=terryjones
    cn=Terry Jones
    gn=Terry
    sn=Jones
    telephoneNumber=123-456-7890
    telephoneNumber=123-456-7891
    mail=tjones@alrac.com
 
上面显示了两个重复的属性。你可以任意使用多个重复属性。重复属性常见的用途是人名,比如:
 
    cn=Terry Jones
    cn=T. Jones
    cn=Terry "codefiend" Jones
    cn=Codefiend
 
这样设置的结果是,搜索任何一个属性值都能成功,所以 Terry Jones 就无所遁形了。后缀(suffix)或命名上下文(naming context)位于 LDAP 层级体系的顶端。在我们这个简单的例子中,后缀是 c=us。近来流行的一种常见办法是使用公司的域名,比如 dc=alrac,dc=net。DC 表示域组件(domain component)。
 
 
Schema、objectClass 与属性
 
当你在 DIT 中创建了一个条目时,它的数据包含在属性中。它们都属于 objectClass。Schema 可以认为是装有 objectClass 的大口袋。所以,当听到某些人讨论 OpenLDAP schema 的时候,你就知道他们指的是定义 OpenLDAP 目录中组织和数据类型的文件。在 OpenLDAP 中,某些 schema 是在 slapd 中硬编码的。
 
objectClass 是 objectClass 层级体系的一部分。它从父母那里继承了所有属性。例如,inetOrgPerson objectClass 是你经常要用到的。如果查看一下 /etc/ldap/schema/inetorgperson.schema,你就能找到这个定义:
 
    objectclass    ( 2.16.840.1.113730.3.2.2
        NAME 'inetOrgPerson'
        DESC 'RFC2798: Internet Organizational Person'
        SUP organizationalPerson
        STRUCTURAL
    
这一段说明该长串 objectClass 数字是一个正式的对象 ID(OID)号码。所有 LDAP OID 都是全局唯一的,你不能自行杜撰。仅在你创建一个定制 schema 并且需要某些新 OID 时,才会有关系。然后,寻找一个注册机构分配一些号码给你,比如 Internet 号码分配机构(IANA)。
 
SUP(上级) organizationalPerson 这一行告诉你,它的上一级 objectClass 是 organizationalPerson,也就是顶级 objectClass person 的子节点。objectClass 定义了所有子节点的必要和可选属性,你可以在任何 LDAP 浏览器中读到。
 
STRUCTURAL 表示该 objectClass 可以用于在你的 DIT 中创建条目,你还能看到 AUXILARY objectClass,这些都不能独立存在,而必须与 STRUCTURAL objectClass 一起使用。
 
objectClass 同样也是一种属性。
 
如果现在不太明白,也别担心。当你创建了一个简单的目录之后,就知道它是如何实现的了。
 
 
“秘密的” RootDSE
 
还有一点你应该知道:rootDSE。这是那些聪明的自我引用式极客名称之一:DSE 表示 DSA 特定条目,而 DSA 表示目录系统代理。这是 LDAP 层级体系中不可见的最高等级条目,也是 LDAP 服务器的内置属性。若要查看它们,可以在 LDAP 服务器上运行以下两条命令:
 
    $ ldapsearch -x -s base -b "" +
    # extended LDIF
    #
    # LDAPv3
    # base <> with scope baseObject
    # filter: (objectclass=*)
    # requesting: +
    #
 
    #
    dn:
    structuralObjectClass: OpenLDAProotDSE
    configContext: cn=config
    namingContexts: dc=alrac,dc=net
    supportedControl: 2.16.840.1.113730.3.4.18
    supportedControl: 2.16.840.1.113730.3.4.2
    [...]
    supportedFeatures: 1.3.6.1.4.1.4203.1.5.4
    supportedFeatures: 1.3.6.1.4.1.4203.1.5.5
    supportedLDAPVersion: 3
    supportedSASLMechanisms: DIGEST-MD5
    supportedSASLMechanisms: CRAM-MD5
    supportedSASLMechanisms: NTLM
    entryDN:
    subschemaSubentry: cn=Subschema
 
    # search result
    search: 2
    result: 0 Success
 
    # numResponses: 2
    # numEntries: 1
    
所有那些长串数字都是正式的对象识别符(OID)。要学习更多关于它们的内容,可访问: http://www.alvestrand.no/objectid/ 。该网站包括了一个可以搜索的数据库,所以你就能查看特定 OID 的含义。
 
这条命令显示同样的输出内容,以及整个 subschema:
 
    $ ldapsearch -x -s base -b "cn=subschema" objectclasses
    [...]
    # Subschema
    dn: cn=Subschema
    objectClasses: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRAC
     T MUST objectClass )
    objectClasses: ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject' DESC 'RF
     C2252: extensible object' SUP top AUXILIARY )
    objectClasses: ( 2.5.6.1 NAME 'alias' DESC 'RFC2256: an alias' SUP top STRUCTU
     RAL MUST aliasedObjectName )
    objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'namedref: named
      subordinate referral' SUP top STRUCTURAL MUST ref )
    objectClasses: ( 1.3.6.1.4.1.4203.1.4.1 NAME ( 'OpenLDAProotDSE' 'LDAProotDSE'
      ) DESC 'OpenLDAP Root DSE object' SUP top STRUCTURAL MAY cn )
    objectClasses: ( 2.5.17.0 NAME 'subentry' SUP top STRUCTURAL MUST ( cn $ subtr
     eeSpecification ) )
    [...]
 
那是跟你的 /etc/ldap/schema 文件完全相同的内容。你无需对 rootDSE 做任何事,这里只是展示一下,看看它长什么样。rootDSE 有时会与 root DN 混淆,但它们不是同一个东西。rootDSE 是你的裸 OpenLDAP 服务器,包括 schema 和所支持的协议。你可能在很多文档中看到 root DN 作为后缀名,或者数据层级体系的基础名出现。我会避免使用 root DN 术语,它太容易混淆了。哦,还有 rootdn。那是目录的超级用户,rootdn 和 rootpw 指令会在 slapd.conf 中出现。是的,这也比较容易混淆。rootdn 权力太大,很多管理员都不喜欢设立 rootdn,而是创建一些在目录内部定义的管理用户。
 
 
决定目录的深度
 
你试图规划未来,而且想把 DIT 设计为可以随着组织成长而自然无缝扩张的架构。这是一个宏伟的目标,那是肯定的!所以,你在考虑把它的结构变得更宽更扁,还是更窄更深。这是所有 LDAP 管理员要面临的问题,而且标准答案永远是“这要看情况而定”。我自己的偏好是采用一种扁平的目录结构,因为这样比较容易维护,而且 LDAP 是为了在一个水平上搜索而进行优化的,而不是在整个层级体系中上下求索。
 
图 12-2 展示了一个具有三个 OU 的 DIT:
 
{{附图}}
图 12-2。DIT 发芽抽枝。
 
这看上去很漂亮,而且很有组织,不是吗?三个不同的部门都有它们各自的 OU,这感觉很舒服,就像一个整洁的文件柜。但是想想这个问题——当 Jenn 从 Upstairs 移动到 Downstairs 时会怎样?你得将她从  Upstairs 删除,还要在 Downstairs 中创建一个新的,这需要不少步骤,无论你有多么高的效率。
 
现在,看看图 12-3。
 
{{附图}}
图 12-3。DIT 被切断了。
 
所有用户都集中到了 People OU。我们如何才能知道他们属于那些部门?通过给他们分配一个额外的 OU 属性,象这样:
 
    dn: cn=Jenn Dancer,ou=people,dc=foo,dc=com
    objectClass: inetOrgPerson
    cn: Jenn Dancer
    ou=Upstairs
    [...]
 
Jenn 想搬到 Downstairs?小菜一碟。我所要做的就是运行 ldapmodify 或者某个图形化的 LDAP 浏览器,将 ou=Upstairs 改为 ou=Downstairs,还有其它变更(例如,电话号码和职位)。这样比把她移动到某个新的 OU 工作量减少一半,只需要下列步骤:
 
 • 将现有条目通过 ldapsearch 输出到一个 LDIF 文件中。
 • 用 ldapdelete 删除记录。
 • 编辑 LDIF 文件。
 • 用 ldapadd 添加到新的 OU 中。
 
你可能还会考虑将权力下放给初级管理员,或者是如何保护敏感数据等问题。可能意味着要把某些数据存储在不同的子树或独立的数据库中,这样会使管理复杂一点,但是可以让你控制谁能获得读写权限。
 
这永远不是一个容易阐述的话题,而且如果你去问另外五位 LDAP 管理员的建议,可能会得到八种不同的意见。Gerald Carter 撰写的《LDAP 系统管理》(O'Reilly),特别有助于考虑规划目录拓扑。
 
 
12.1 在 Debian 上安装 OpenLDAP 
 
问题
 
你准备开始工作,并且让 OpenLDAP 启动运行。在 Debian 上的最佳安装方式是什么?
 
 
解决方案
 
只要运行 Aptitude 并且安装这些软件包:
 
    # aptitude install slapd ldap-utils gq db4.3-doc db4.2-util
 
你会被问及,是否创建一个 LDAP admin 密码。Debian 然后就会创建 LDAP admin 用户,并且将你现有的域名作为后缀,或者命名上下文。
 
然后,执行一次简单的搜索,确认服务器是否正在运行,以及能否响应请求:
 
    # ldapsearch -xb '' -s base '(objectclass=*)' namingContexts
    [...]
    dn:
    namingContexts: dc=alrac,dc=net
    [...]
 
运行这条命令以展示 admin 用户:
 
    $ ldapsearch -xb 'dc=alrac,dc=net'
    [...]
    # admin, alrac.net
    dn: cn=admin,dc=alrac,dc=net
    objectClass: simpleSecurityObject
    objectClass: organizationalRole
    cn: admin
    description: LDAP administrator
    [...]
 
很好!结果说明是成功的。现在,你可以继续进行后面的步骤了。
 
 
讨论
 
Debian 创建了一个裸配置,还有一个 openldap 用户,你可以在 /etc/passwd 中看到,创建了启动文件并且在开机时启动,还给所有文件设置了正确的属主和权限。它还创建了 OpenLDAP admin 用户,它并不是像 openldap 这样的系统用户,而是一个位于 OpenLDAP 目录中的用户。
 
你可能已经在 OpenLDAP How-to 文档中看到要到 slapd.conf 中创建一个 rootdn 和 rootpw。rootdn 是数据库的超级用户,就像我们的 admin 用户,而 rootpw 是 rootdn 的口令。对于第一次创建的目录这是必需的,而且你可能喜欢以这种方式配置你的数据库超级用户。rootdn 会自动获得不受限制的所有访问权限,而且不需要访问控制,我们的 admin 用户也一样。
 
某些管理员出于安全的考虑,不想在 slapd.conf 中设置 rootpw。某些管理员不想在目录中设置超级用户,比如我们的 admin 用户,也同样出于安全的理由。如果你一定要将它保留在 slapd.conf 中,那么就得再三确认该文件被妥善保护——让它只能被属主和组所有者读取,并且只在你需要变更时打开写权限。
 
OpenLDAP 依赖于 Sleepycat Berkeley DB 作为其后端数据库。Aptitude 应该会把你需要的版本拉进来。db4.2-util 软件包含有管理 BDB 的基本命令。
 
db4.3-doc 软件包含有完整的 Sleepycat BDB 手册。它的目标读者是程序员,但是也包括了很多对于服务器管理员有用的信息。(不存在 db4.2-doc 软件包,软件包版本不匹配没有关系。)
 
获取与 Berkeley DB 版本匹配的 db4.*-util 版本。如果你不知道要找哪个软件包名称,dpkg 可以显示你的系统中已经安装的版本:
 
    $ dpkg -l | grep db4
    ii libdb4.2      4.2.52+dfsg-2 Berkeley v4.2 Database Libraries [runtime]
    ii libdb4.3      4.3.29-8      Berkeley v4.3 Database Libraries [runtime]
    ii libdb4.4      4.4.20-8      Berkeley v4.4 Database Libraries [runtime]
 
你可能会有多个版本,因为大量应用程序都使用 Berkeley DB 作为它们的后端。通过 apt-cache 寻找正确的 slapd 版本:
 
    $ apt-cache depends slapd | grep db4
    Depends: libdb4.2
 
你可以看到自己的后缀,也就是目录的基础名称,在 /etc/ldap/slapd.conf 中:
 
    # The base of your directory in database #1
    suffix          "dc=alrac,dc=net"
 
这里是 ldapsearch 各选项的含义:
 
-x
    通过明文验证绑定到目录。
    
-b
    开始搜索。
    
-s
    定义搜索范围。你的选项是 base、one 或者 sub。base 表示搜索 base 对象,one 搜索某个条目的直接子节点,但不包括条目本身,sub 搜索整个子树以及该条目。默认值为 sub。
    
你可以从源码安装,如果真想这么做的话。请访问 OpenLDAP.org(http://www.openldap.org/)获取更多说明。
 
 
参阅
 
 • man ldapsearch
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 
 
12.2 在 Fedora 上安装 OpenLDAP
 
问题
 
你准备开始工作,并且让 OpenLDAP 启动运行。在 Fedora 上的最佳安装方式是什么?
 
 
解决方案
 
只要运行 Yum 并且安装这些软件包:
 
    # yum install openldap openldap-servers openldap-clients db4-utils gq
 
 
讨论
 
Fedora 的 OpenLDAP 实现需要花一点工夫。你得从头开始配置,修正某些文件属性,还要创建一个数据库配置文件——我们会在下一节中讲述。它会创建启动文件和一个 ldap 系统用户,而 Yum 负责处理依赖关系。
 
你可以从源码安装,如果真想这么做的话。请访问 OpenLDAP.org(http://www.openldap.org/)获取更多说明。
 
 
参阅
 
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 
 
12.3 配置并测试 OpenLDAP 服务器
 
问题
 
安装 OpenLDAP 服务器很顺利,现在你该如何启动并进行测试?
 
 
解决方案
 
Debian 用户不需要阅读本节,因为 Debian 安装程序已经完成了所有工作,但无论如何,回顾一下总是有帮助的。
 
Fedora 用户,拷贝这个例子:/etc/openldap/slapd.conf。在括号中替换上你自己的域名(任何一个都行,甚至 example.com),并且填上你自己的 rootpw:
 
    #######################################################################
    # Global Directives:
 
    # Schema and objectClass definitions
    include          /etc/ldap/schema/core.schema
    include          /etc/ldap/schema/cosine.schema
    include          /etc/ldap/schema/nis.schema
    include          /etc/ldap/schema/inetorgperson.schema
 
    pidfile          /var/run/slapd/slapd.pid
    argsfile         /var/run/slapd/slapd.args
 
    # Read slapd.conf(5) for possible values
    loglevel         -1
 
    # Where the dynamically loaded modules are stored
    modulepath     /usr/lib/ldap
    moduleload     back_bdb
 
    # The maximum number of entries that is returned for a search operation
    sizelimit 500
 
    # The tool-threads parameter sets the actual amount of cpus that is used
    # for indexing.
    tool-threads 1
 
    #######################################################################
    # Specific Backend Directives for bdb:
    # Backend specific directives apply to this backend until another
    # 'backend' directive occurs
    backend         bdb
    checkpoint 512 30
 
    #######################################################################
    # Specific Directives for database #1
    database         bdb
    suffix "dc=[alrac],dc=[net]"
    rootdn "cn=admin,dc=[alrac],dc=[net]"
    rootpw [password]
 
    # Where the database file are physically stored for database #1
    directory        "/var/lib/ldap"
 
    # Indexing options for database #1
    index            objectClass eq
 
    # Save the time that the entry gets modified, for database #1
    lastmod         on
 
    # admin can read/write all passwords
    # users can change their own passwords
    access to attrs=userPassword,shadowLastChange
            by dn="cn=admin,dc=alrac,dc=net" write
            by anonymous auth
            by self write
            by * none
 
    # many applications need read access to the rootDSE
    # especially to read supported SASL mechanisms
    # this restricts them to the rootDSE; they cannot read past this level
    access to dn.base="" by * read
 
    # admin gets unlimited read/write access to database
    # everyone else read-only
    access to *
            by dn="cn=admin,dc=alrac,dc=net" write
            by * read
    #######################################################################
    
然后,确认 /var/lib/ldap 中的文件都为 ldap 用户所有:
 
    # chown -R ldap:ldap /var/lib/ldap
    
如果没有 /var/lib/ldap/DB_CONFIG 文件,就创建一个空的:
 
    # touch /var/lib/ldap/DB_CONFIG
    
下一步,运行 slaptest 命令检查 /etc/ldap/slapd.conf:
 
    # slaptest
    config file testing succeeded
 
现在,启动它:
 
    # /etc/init.d/ldap start
    Checking configuration files for slapd: config file testing succeeded
                                                               [ OK ]
    Started slapd:                                             [ OK ]
 
最后,运行这个简单的测试,确认服务器正在运行并且可以响应请求:
 
    # ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
    [...]
    dn:
    namingContexts: dc=alrac,dc=net
    [...]
 
很好!结果说明是成功的。现在,你可以继续进行后面的步骤了。
 
 
讨论
 
Debian 用户不需要 rootpw 或 rootdn,无论如何,这些都会在下一节中讲到。
 
loglevel -1 表示记录一切,而且这样可能会在瞬间将数兆日志打入 syslog。参阅第 12.12 节获取更多信息。
 
参阅第 12.1 节讨论部分中关于 ldapsearch 选项的解释。
 
当你运行 slaptest 时,你可能会看到警告提示。slapd 应该还是会运行,但是应该修复任何引发警告提示的问题。Fedora 上某些常见错误是由以下原因引起:
 
 • 不正确的文件权限或属主
 • 丢失了 /var/lib/ldap/DB_CONFIG
 
按照本节所介绍的步骤进行,应该可以防止出现任何错误。例如,如果 /var/lib/ldap 中的文件并非 ldap 用户所有,你将会得到 “permission denied” 错误。如果 DB_CONFIG 丢失,你会得到一次警告提示,但 slapd 还是会运行。
 
DB_CONFIG 包含了用于调整 Berkeley DB 后端的选项。参阅第 12.11 节学习如何配置。
 
这只是用于测试基本功能的简单安装,在 slapd.conf 中设置一个 rootpw 口令,从安全角度来看并不是最佳的实践,而且我们并没有真正建立一个目录。但是我们正在接近目标。
 
 
参阅
 
 • man ldapsearch
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 
 
12.4 在 Fedora 上创建一个新数据库
 
问题
 
你的 Fedora OpenLDAP 安装并没有包括一个管理用户,也没有其它任何用户。你需要创建一个 admin 用户来管理目录,而且你还需要定义后缀。
 
 
解决方案
 
这里有三个步骤:
 
 1. 用新的信息创建一个 LDIF 文件。
 2. 使用 ldapadd 命令将新条目添加到 Berkeley DB。
 3. 在 slapd.conf 中配置读写权限。
 
首先,创建 LDAP 数据交换格式(LDIF)文件,在这个例子中名为 first.ldif。替换你自己的域名、公司名、描述,还有口令。去掉所有前导和尾随的空格。用一个空行分隔条目,注释必须位于它们自己所在的行上,而且在每个冒号后面必须有一个空格:
 
    ##first.ldif
    # root dn entry
    dn: dc=alrac,dc=net
    objectclass: dcObject
    objectclass: organization
    o: Alrac's Fine Cookies and Beer
    dc: alrac
 
    # directory administrator
    dn: cn=admin,dc=alrac,dc=net
    objectClass: simpleSecurityObject
    objectClass: organizationalRole
    cn: admin
    userPassword: bigsecretword
    description: LDAP administrator
 
第二步,运行这条 ldapadd 命令。你会被问及 slapd.conf 中输入的 rootpw 口令:
 
    # ldapadd -x -D "cn=admin,dc=alrac,dc=net" -W -f first.ldif
    Enter LDAP Password:
    adding new entry "dc=alrac,dc=net"
    adding new entry "cn=admin,dc=alrac,dc=net"
 
让我们看看新条目:
 
    $ ldapsearch -x -b 'dc=alrac,dc=net'
    [...]
    # alrac.net
    dn: dc=alrac,dc=net
    objectClass: dcObject
    objectClass: organization
    o: Alrac's Fine Cookies and Beer
    dc: alrac
 
    # admin, alrac.net
    dn: cn=admin,dc=alrac,dc=net
    objectClass: simpleSecurityObject
    objectClass: organizationalRole
    cn: admin
    userPassword: fji8Hu11hs
    description: LDAP administrator
    [...]
 
在 slapd.conf 中注释 rootpw 和 rootdn 条目。然后,重启 OpenLDAP,并且再次查看目录条目:
 
    # /etc/init.d/ldap restart
    $ ldapsearch -x -b 'dc=alrac,dc=net'
 
现在,admin 用户就拥有了完全的数据库控制权。
 
 
讨论
 
注意 LDIF 文件中的空格。一个空行用于划分条目界限。某一行的前导空格表示该行是前一行的后续,逗号分隔每个名/值对,而任何文字中的逗号必须转义,就像这个例子所示:
 
    dn: uid=twhale,ou=people,ou=factory,ou=bluecollars,
       o=widgets\, inc.,c=au,dc=widgets,dc=com
 
admin 用户可以拥有任何名字,比如 db-admin 或 ldapgoddess,或者任何你喜欢的名字。你会在很多 LDAP 文档中看到 Manager 用户,和我们的 admin 用户一样。
 
first.ldif 文件包含两个独立的条目。第一个条目定义了我们的后缀。那是整个目录树的根。第二个条目定义了 admin 用户,它在 slapd.conf 中被赋予了整个数据库的读写权限。所有其它用户只给了读权限。他们可以更改自己的口令,而且无法看到他人的口令。
 
每个条目都要有自己的唯一 DN。记住,这些是由相对识别名(RDN)和它所有的祖先结合在一起构成的。(参阅本章的介绍部分,获取更多信息。)
 
你的 LDIF 文件不必使用 .ldif 文件后缀。保留它则毫无疑问不会导致混淆。
 
为什么要更换 slapd.conf 中的 rootdn 和 rootpw?rootdn 是数据库的超级用户,就像我们的 admin 用户,而 rootpw 是 rootdn 的口令。对于初次创建目录是有用的,而且你可能喜欢通过这种方式来配置你的数据库超级用户。某些管理员出于安全的考虑,不想在 slapd.conf 中设置 rootpw。某些管理员不想在目录中设置超级用户,比如我们的 admin 用户,也同样出于安全的理由。如果你一定要将它保留在 slapd.conf 中,那么就得再三确认该文件被妥善保护——让它只能被属主和组所有者读取,并且只在你需要变更时打开写权限。
 
如果你选择保留 slapd.conf 中的 rootdn,那么我们在前一节中创建的 admin ACL 就没有必要了。rootdn 不需要显式的访问规则。
 
 
ObjectClass 与属性
 
打开一个图形化 LDAP 浏览器,如 gq,查看每个 ObjectClass 可用的属性。这是一种查看选项的简单方式。你也可以在 /etc/ldap/schema/(Fedora 上是 /etc/openldap)中查看 schema 文件。inetOrgPerson 是你将经常用到的一个。/etc/ldap/schema/inetorgperson.schema 定义了那些属性是必要的,而那些是可选的:
 
    # inetOrgPerson
    # The inetOrgPerson represents people who are associated with an
    # organization in some way. It is a structural class and is derived
    # from the organizationalPerson which is defined in X.521 [X521].
    objectclass     ( 2.16.840.1.113730.3.2.2
        NAME 'inetOrgPerson'
        DESC 'RFC2798: Internet Organizational Person'
        SUP organizationalPerson
        STRUCTURAL
        MAY (
            audio $ businessCategory $ carLicense $ departmentNumber $
            displayName $ employeeNumber $ employeeType $ givenName $
            homePhone $ homePostalAddress $ initials $ jpegPhoto $
            labeledURI $ mail $ manager $ mobile $ o $ pager $
            photo $ roomNumber $ secretary $ uid $ userCertificate $
            x500uniqueIdentifier $ preferredLanguage $
            userSMIMECertificate $ userPKCS12 )
        )
 
如上所示,它们都是可选的。simpleSecurityObject 不那么复杂,它只有一个必要的属性:
 
    objectclass ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
        DESC 'RFC1274: simple security object'
        SUP top AUXILIARY
        MUST userPassword )
 
 
参阅
 
 • man 1 ldapsearch
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.5 在你的目录中添加更多用户
 
问题
 
你准备往 OpenLDAP 目录中添加更多用户。你该怎么做?
 
 
解决方案
 
确认 OpenLDAP 服务器正在运行。下一步,创建一个 LDIF 文件,其中包含你的新用户条目,然后使用 ldapadd 将它们输出到 OpenLDAP 目录中。
 
我们正准备稍微扩展一下目录结构,因为现在这只是一个老式的单层目录。我们想要对数据进行整理,不要把所有内容都放在顶层,所以我们将会添加一个 people 组织单元(OU)。我们的目录现在看上去如图 12-4。
 
{{附图}}
图 12-4。添加一个新的 OU 及相关用户
 
你可以看到我们的 admin 正孤立在外。(它在顶层孤立。)
 
这个 users.ldif 样例文件添加了新的 OU 和两个用户。注意你的空格!注释必须位于它们自己所在的行上,而且在每个冒号后面必须有一个空格,还要用空行分隔条目:
 
    ##/etc/ldap/ldif/users.ldif
    dn: ou=people,dc=alrac,dc=net
    ou: people
    description: All people in organisation
    objectClass: organizationalUnit
 
    dn: uid=cschroder,ou=people,dc=alrac,dc=net
    objectClass: inetOrgPerson
    cn: Carla Schroder
    sn: Schroder
    uid: cschroder
    userPassword: password
    telephoneNumber: 444-222-3333
    homePhone: 555-111-2222
    mail: carla@bratgrrl.com
    mail: carla@gmail.com
    description: indescribable
 
    dn: uid=thanson,ou=people,dc=alrac,dc=net
    objectClass: inetOrgPerson
    cn: Terry Hanson
    sn: Hanson
    uid: thanson
    userPassword: password
    telephoneNumber: 222-333-4455
    homePhone: 112-334-5678
    mail: terry@bratgrrl.com
    mail: terry@gmail.com
    description: absolutely fabulous
 
现在,将这些新条目添加到数据库:
 
    # ldapadd -x -D "cn=admin,dc=alrac,dc=net" -W -f users.ldif
    Enter LDAP Password:
    adding new entry "ou=people,dc=alrac,dc=net"
    adding new entry "uid=cschroder,ou=people,dc=alrac,dc=net"
    adding new entry "uid=thanson,ou=people,dc=alrac,dc=net"
 
然后,运行常用的 ldapsearch 命令验证你的条目:
 
    $ ldapsearch -x -b 'dc=alrac,dc=net'
 
若要添加更多用户,你就需要创建一个新的 .ldif 文件,或者覆盖旧的文件。你不能只添加新条目到现有的文件中,因为当 ldapadd 找到某个现有的条目时,它会停止并且不再往下读取文件剩余部分。
 
 
讨论
 
ldapadd 要求有一个正在运行的服务器,如果 slapd 不在运行,那么它就无法工作。所有以“ldap”开头的命令在要在运行的服务器上操作。而“slap”命令,如 slapcat 和 slapadd,要求 slapd 不在运行状态。参阅前一节的讨论部分,学习创建 LDIF 文件相关细节要点。
 
 
参阅
 
 • man 1 ldapsearch
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.6 修正目录条目
 
问题
 
由于用户变更,或者你操作失误,所以想要改变一个现有的目录条目。你该怎么做?
 
 
解决方案
 
一种途径是使用 ldapmodify。你需要创建一个新的特殊格式 LDIF 文件。这个例子添加了一个标题,变更了 email 地址,并且添加了一张照片:
 
    ##/etc/ldap/modfile.ldif
    dn: uid=thanson,ou=people,dc=alrac,dc=net
    changetype:modify
    add:title
    title:Fire Marshal
    -
    replace:mail
    mail:terry@wolfgrrl.com
    -
    add: jpegphoto
    jpegphoto:< file:///filename.jpg
 
下一步,以这种方式使用 LDIF 文件:
 
    # ldapmodify -x -D "cn=admin,dc=alrac,dc=net" -W -f modfile.ldif
    Enter LDAP Password:
    modifying entry "cn=Terry Hanson,ou=people,dc=alrac,dc=net"
 
然后,通过 ldapsearch 验证:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' 'cn=terry hanson'
    [...]
    # Terry Hanson, people, alrac.net
    dn: cn=Terry Hanson,ou=people,dc=alrac,dc=net
    objectClass: inetOrgPerson
    cn: Terry Hanson
    sn: Hanson
    uid: thanson
    telephoneNumber: 333.444.4545
    homePhone: 222-333-5555
    description: burning down the house
    title: Fire Marshal
    mail: terry@wolfgrrl.com
    jpegPhoto:< file:///tmp/ldapsearch-jpegPhoto-Sx11P8
    [...]
 
 
讨论
 
对于少量条目的变更,图形化 LDAP 浏览器(见第 12.10 节)通常比较快,也比较方便。使用 LDIF 用于大量变更比较快,而且适合顶尖的脚本专家。
 
注意 ldapsearch 新的 -t 选项。该选项告诉 ldapsearch 要存储照片、音频文件,或者其它非字符数据的临时文件。如果你不使用它,那么就会得到大量编码,象这样:
 
    fdtvWuJG2BwGFzjms1d7eTubLmBp5EFktAAPZfvNUzNVthoyz6sMbkgtSAd6dj3mqudjOCW6QxUAItBmSbQw
    638J7W+NQArNTIZ4wNQbkdXh3sATNVnpSns2yveXHeYU5+1o46yelp6pu02LGcYBKimkNyRuq/j+/QUGJBp
    3mdwf3q2PTbca2gFkCkkKVRixIltTMw4m3+91vTmZYaGy5Ktbxnq0
 
当你添加 JPEG 照片时,它必须是可用的,否则 ldapmodify 会返回消息 ldapmodify: invalid format。虽然该消息跟“我找不到那个文件”完全不同,但这就是它实际上的意思。JPEG 文件以 base-64 MIME 编码格式导入数据库。如果你准备包含人们的 ID 照片,就要确认它们的物理尺寸和文件大小都是比较小的,否则它们会在 LDAP 客户端上看起来很奇怪。
 
OpenLDAP 对待变更文件的格式和语法十分苛刻。从 DN 开始标识条目,然后关键词 changetype 后面要跟随变更类型: add、modify、modrdn 或 delete。删除一个条目只需要两行:
 
    dn: cn=Terry Hanson,ou=people,dc=alrac,dc=net
    changetype:delete
 
jpegPhoto 和 audio 属性的语法都很讲究:
 
    jpegphoto:< file:///filename.jpg
    
:< 中间不能有空格,而后面要跟一个空格。file:// 有两个斜杠,然后是文件名。
 
当你修改一个现有的条目时,可能用到的关键词是 add、replace 或 delete。replace 是全部或者全不,例如,如果该条目有三个 email 地址,而你的 LDIF 文件包含:
 
    replace: mail
    mail: thanson@foosite.com
 
它就会删除三个旧地址,然后添加这个新地址。
 
delete 也可以是全部或全不,或者可选。如果你的条目中有三个 homePhone 属性,而你使用:
 
    delete: homephone
    
那么所有三个都会被删除。要删除一个单独的属性,这么做:
 
    delete: homephone
    homePhone: 222-333-5555
 
 
参阅
 
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.7 连接至远程 OpenLDAP 服务器
 
问题
 
你不会总是待在物理服务器旁边,或者你想要托管服务器,所以需要知道如何远程管理你的 OpenLDAP 服务器。
 
 
解决方案
 
所有 OpenLDAP 命令都使用同样的 -H 选项连接远程主机,如这个例子中,在本地网络使用服务器的主机名:
 
    # ldapsearch -H ldap://xena -xtb 'dc=alrac,dc=net'
    
或者,你可以使用完全限定的域名:
 
    # ldapsearch -H ldap://xena.alrac.net -xtb 'dc=alrac,dc=net'
    
或者,指定端口。你无需这么做,除非要使用别的端口:
 
    # ldapsearch -H ldap://xena.alrac.net:389 -xtb 'dc=alrac,dc=net'
    
 
讨论
 
大量文档仍提到要使用小写的 -h,但是该选项已经不再使用了,而且未来即将被废弃。
 
并非只能在样例命令中使用这些选项,任何 OpenLDAP 命令都可以远程执行(例如,搜索、变更,等等)。
 
 
参阅
 
 • man 1 ldapsearch
 • man 1 ldapmodify
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.8 在你的 OpenLDAP 目录中搜索
 
问题
 
你的目录正在增长,而你想知道如何细化搜索,以便只摘出所需要的信息,而不用在一大堆无关的信息里跋涉。
 
 
解决方案
 
ldapsearch 命令附带了一系列选项,用于搜索任何一个可以想到的属性。这条命令通过 common name(CN)搜索指定的用户:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' 'cn=carla'
    
如果你不太确定要查找什么,就可以使用通配符。这个例子搜索以 schroder 结尾的 UID:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' 'uid=*schroder'
 
也许你想要获得所有以某个电话前缀开头的条目:
 
    $ ldapsearch -xtb 'ou=people,dc=alrac,dc=net' '(telephoneNumber=333*)'
    
你可能只是想要一份属性列表,而不含相应内容:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' 'cn=carla' -A
    
你可以从 DIT 的另一个层次开始:
 
    $ ldapsearch -xtb 'ou=people,dc=alrac,dc=net' 'cn=carla'
    
你可以限制搜索的规模,如这个例子中搜索照片条目,并且限制结果为 10 条:
 
    $ ldapsearch -z 10 -xtb 'ou=people,dc=alrac,dc=net' '(jpegPhoto=*)'
    
这条命令建立了一份目录所用 objectClass 的列表:
 
    $ ldapsearch -xb 'dc=alrac,dc=net' '(objectclass=*)' dcObject
    
或者,搜索指定 objectClass 的条目:
 
    $ ldapsearch -xb 'dc=alrac,dc=net' '(objectclass=simpleSecurityObject)'
    
组合属性以缩小搜索范围,比如拥有特定电话前缀和邮件域的用户:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' '(&(mail=*domain.com)(telephoneNumber=333*))'
    
或者,列出某个指定邮件域中的所有用户,除具有指定电话前缀(注意你的括号)之外:
 
    $ ldapsearch -xtb 'dc=alrac,dc=net' '(&(mail=*domain.com)(!(telephoneNumber=333*)))'
    
    
讨论
 
如果你正在想,“忘掉它,我要走捷径,用那些漂亮的图形化 LDAP 客户端”。慢着,那些漂亮的图形化界面还是需要关于 OpenLDAP 命令的知识。
 
这里是一些用于多种搜索表达式的语法样例:
 
匹配该值
    (attribute=value)
    (objectclass=name)
 
近似匹配该值,这需要一个近似指数,参阅第 12.9 节获取更多信息
    (attribute~=value)
    
匹配所有这些值
    (&(exp1)(exp2)(exp3))
 
匹配其中任何一个值,exp1 OR exp2 OR exp3
    (|(exp1)(exp2)(exp3))
    
排除该值
    (!(exp1))
 
这些值都排除
    (&(!(exp1))(!(exp2)))
    
排除任何一组值
    (|(!(exp1))(!(exp2)))
    
还有一些其它可用的搜索类型,尽管如此,我还是没有发现它们有什么用,因为这些搜索类型依赖于属性的排序规则,而它们多数都没有此类规则:
 
匹配大于的结果
    (attribute>=value)
 
匹配小于的结果
    (attribute<=value)
 
 
参阅
 
 • man 1 ldapsearch
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.9 为你的数据库建立索引
 
问题
 
你注意到 slapd.conf 中有一些索引选项——那些都是干什么用的?它们可以让你的目录查询更快么?
 
 
解决方案
 
它们确实可以。索引经常搜索的属性将会提高性能。这里是一些不同用途的索引样例:
 
    #always have this one
    index objectClass eq
 
    #for common name searches
    index cn,sn,uid   pres,eq,sub
 
    #email address searches
    index mail   pres,eq
 
这些配置都在 slapd.conf 中。
 
 
讨论
 
如果你在 slapd 运行时改变了索引设置,那么一个内部的任务就会自动运行,并生成新的索引。你无需显式重新生成索引。尽管如此,如果 slapd 在索引任务完成之前停止,那么就得手工通过 slapindex 命令生成新的索引:
 
    # /etc/init.d/slapd stop (Debian)
    # /etc/init.d/ldap stop (Fedora)
    # slapindex
 
当它完成时,重新启动 OpenLDAP。如果你有一个比较大的目录,这个过程会消耗若干分钟。
 
建立索引会使 id2entry 文件大小增长。数据库越大,索引越多,该文件就会变得越大。来自 OpenLDAP-devel 邮件列表的这份邮件(http://www.openldap.org/lists/openldap-devel/200510/msg00131.html)说:
 
    对于我的测试数据库而言,360 MB 的输入 LDIF 和 285,000 个条目,以及 15 个索引属性,使用 512 MB BDB 缓存.... 最终的 id2entry 数据库大约有 800 MB,加上所有的索引,总大小约为 2.1 GB。
    
索引语法为:
 
    index [attributes] [index type]
    
多个属性和索引类型是用逗号分隔的。这些是最常用的索引类型:
 
pres
    匹配属性类型,而不是属性值。例如,搜索属性  (objectclass=inetOrgPerson) 或 (attribute=mail)。
    
eq
    匹配确切的属性值,如 (cn=fred) 只返回确切匹配“fred”的结果。
    
sub
    通配符搜索索引,如 (cn=lisa*)。有多种不同的 sub。例如,subinitial 是为 (cn=lisa*) 之类的搜索进行优化的,subfinal 是为 (cn=*smith) 之类的搜索进行优化的,而 subany 是为 (cn=*isa*) 之类的搜索进行优化的。
    
创建不必要的索引会影响性能。未索引的搜索总是会成功,你的目标是索引最常用的搜索,而不要担心不常用的搜索类型。聪明的索引可以显著提升性能。观察你的日志文件,看看你的用户或应用程序都在查找什么,那是你决定什么需要索引的最佳参考指南。参阅第 12.12 节,获得更多信息。
 
 
参阅
 
 • man 8 slapindex
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.10 使用图形界面管理你的目录
 
问题
 
你想要一些漂亮的图形化工具用于管理 LDAP 目录。
 
 
解决方案
 
有非常多的图形化 LDAP 目录查看器和管理器,它们的用途和特点多种多样。你还是需要知道 OpenLDAP 命令,但是一个好的图形化界面可以让你更有效率。这里是一些优秀的开源应用程序:
 
GQ (http://gq-project.org/)
    这是一个非常简单的独立 LDAP 客户端。它是一个浏览器,也是一个编辑工具。你可以很方便地浏览 schema 细节,还能看到你的目录结构,如图 12-5 所示。你也可以通过验证创建或编辑条目。
    
Web 浏览器
    Konqueror 和 Internet Explorer 都包括了简单的 LDAP 查看器。你可以看到你的目录,但是不能编辑它。输入一个含有前缀的 URL,如 ldap://localhost:389/dc=alrac,dc=net ,然后就能看到如图 12-6 所示结果。
    
LAT,LDAP 管理工具(http://dev.mmgsecurity.com/projects/lat/)
    一个漂亮而且功能丰富的查看器和编辑工具(见图 12-7)。它包括了用于 Samba 和活动目录集成的工具,一个很好的搜索工具,LDIF 导入和导出,以及其它基本的管理特性。
    
基于 Web 的 LDAP 管理器
    phpLDAPadmin(http://phpldapadmin.sourceforge.net/)和 Gosa(https://www.gosa-project.org/)是两种流行的基于 web 的 LDAP 管理器。它们都非常复杂,就像多数 PHP 应用程序一样,因为它们依赖于 HTTP 服务器、PHP 和多种模块及相应的库。所以它们都需要花点工夫学习,但它们的好处是,都有颇具吸引力的界面,通用的客户端,还有任何 PHP 程序员都能扩展定制它们。
    
{{附图}}
图 12-5。GQ 查看 LDAP 目录视图
 
{{附图}}
图 12-6。Konqueror 中看到我们的 LDAP 目录
 
 
讨论
 
就像所有优秀的 Linux 管理员一样,你不会在 LDAP 服务器上运行 X Windows,以及所有相关应用程序,你不需要它们,因为它们都支持安全的远程访问。
 
{{附图}}
图 12-7。LAT 的目录视图
 
 
参阅
 
 • OpenLDAP.org: http://www.openldap.org/
 • 《LDAP 目录详解:介绍与分析》,Brian Arkills 著 (Addison-Wesley)
 • 《LDAP 系统管理》,Gerald Carter 著 (O’Reilly)
 
 
12.11 配置 Berkeley DB 
 
问题
 
你知道自己需要使用 /var/lib/ldap/DB_CONFIG 来配置 LDAP 目录的数据库后端(Berkeley DB),从而使它可以精力充沛地工作,而不会陷入泥沼。你如何知道要使用哪些选项和值?
 
 
解决方案
 
我们将从某些对于入门者合适的值开始,然后学习如何通过计算来细化它们。
 
记得要检查你的 slapd.conf,如果存在重复的 BDB 条目就要清除掉。它们可以放在不同的文件中,但最好是都保留在 DB_CONFIG 中。你不想要那些重复或者冲突的条目。
 
首先,确认在 slapd.conf 中有一个 cachesize 条目:
 
    cachesize 5000
    
然后,在 /var/lib/ldap/DB_CONFIG 中输入这些选项和值:
 
    ##/var/lib/ldap/DB_CONFIG
    set_cachesize 0 1048576 0
    set_lk_max_objects 1500
    set_lk_max_locks 1500
    set_lk_max_lockers 1500
    #
    #logging settings
    set_lg_regionmax 1048576
    set_lg_bsize 32768
    set_lg_max 131072
    set_lg_dir /var/log/openldap
 
set_cachesize 值是以字节为单位的,而且必须是 2 的乘方,所以例子中的数值为一兆。你如何知道该用多少?在 Debian 上使用 db4.2_stat 命令,而在 Fedora 上使用 db_stat 命令,从两个主数据库文件 id2entry.bdb 和 dn2id.bdb 中生成统计信息:
 
    # db4.2_stat -d /var/lib/ldap/id2entry.bdb
    53162   Btree magic number.
    9       Btree version number.
    Flags: little-endian
    2       Minimum keys per-page.
    16384   Underlying database page size.
    1       Number of levels in the tree.
    6       Number of unique keys in the tree.
    6       Number of data items in the tree.
    0       Number of tree internal pages.
    0       Number of bytes free in tree internal pages (0% ff).
    1       Number of tree leaf pages.
    12374   Number of bytes free in tree leaf pages (24% ff).
    0       Number of tree duplicate pages.
    0       Number of bytes free in tree duplicate pages (0% ff).
    0       Number of tree overflow pages.
    0       Number of bytes free in tree overflow pages (0% ff).
    0       Number of pages on the free list.
 
    # db4.2_stat -d /var/lib/ldap/dn2id.bdb
    53162   Btree magic number.
    9       Btree version number.
    Flags: duplicates, little-endian
    2       Minimum keys per-page.
    4096    Underlying database page size.
    1       Number of levels in the tree.
    13      Number of unique keys in the tree.
    19      Number of data items in the tree.
    0       Number of tree internal pages.
    0       Number of bytes free in tree internal pages (0% ff).
    1       Number of tree leaf pages.
    3378    Number of bytes free in tree leaf pages (18% ff).
    0 Number of tree duplicate pages.
    0 Number of bytes free in tree duplicate pages (0% ff).
    0 Number of tree overflow pages.
    0 Number of bytes free in tree overflow pages (0% ff).
    0 Number of pages on the free list.
 
你可以看到每个 id2entry.bdb 页面都需要 16 KB,而 dn2id.bdb 需要 4 KB 每页,还有每个文件使用内部页面的数量。所以,你可以使用这个公式计算最小的内存需求:
 
    ((50+1) * 4096) + ((12+1) * 16384)) = 421,888 bytes
 
这里不需要计算其它库的开销或者索引。作为快捷方式,将这个数字加倍就能获得相当好的性能。所以,对于这个例子来说,我们可以将它确定为 1 MB 内存。
 
你如何知道哪些值要分配给 set_lk_max_objects 1500、set_lk_max_locks 1500 和 set_lk_max_lockers 1500?使用 db4.2_stat -c(在 Fedora 上是 db_stat)命令:
 
    # cd /var/lib/ldap
    # db4.2_stat -c
    100     Last allocated locker ID.
    2147M   Current maximum unused locker ID.
    9       Number of lock modes.
    1500    Maximum number of locks possible.
    1500    Maximum number of lockers possible.
    1500    Maximum number of lock objects possible.
    3       Number of current locks.
    11      Maximum number of locks at any one time.
    12      Number of current lockers.
    19      Maximum number of lockers at any one time.
    3       Number of current lock objects.
    8       Maximum number of lock objects at any one time.
    1170    Total number of locks requested.
    1167    Total number of locks released.
    0       Total number of lock requests failing because DB_LOCK_NOWAIT was set.
    0       Total number of locks not immediately available due to conflicts.
    0       Number of deadlocks.
    0       Lock timeout value.
    0       Number of locks that have timed out.
    0       Transaction timeout value.
    0       Number of transactions that have timed out.
    552KB   The size of the lock region..
    0       The number of region locks granted after waiting.
    2579    The number of region locks granted without waiting.
 
对于一个较小的目录,1500 是个合理的起点,通过你的 db4.2_stat -c 执行结果决定是否需要增加。当使用率达到设定值 85% 时,就要增加它们。还要查看你的 Number of current values 输出结果、超时值和失败信息。    
 
对于 OpenLDAP 2.3 及以上版本,你在变更 DB_CONFIG 之后所要做的就是重启 slapd:
 
    # /etc/init.d/slapd restart (Debian)
    # /etc/init.d/ldap restart (Fedora)
 
尽管如此,这样不会总是生效,所以如果 slaptest 返回错误,而且版本为 2.2 及更早的话,Debian 用户需要使用数据库恢复命令:
 
    # /etc/init.d/slapd stop
    # db4.2_recover -h /var/lib/ldap
    # /etc/init.d/slapd start
 
Fedora 用户使用略有不同的命令:
 
    # /etc/init.d/ldap stop
    # db_recover -h /var/lib/ldap
    # /etc/init.d/ldap start
 
然后,运行这条命令验证你的新缓存大小。这些都是基于 DB_CONFIG 设定值为 16777216 的例子。同样,Debian 命令在前,Fedora 在后:
 
    # db4.2_stat -h /var/lib/ldap -m | head -n 2
    20MB 1KB 604B   Total cache size.
    1       Number of caches.
    # db_stat -h /var/lib/ldap -m | head -n 2
 
现在,当 slapd 运行时要留意性能。转到数据库存储的目录:
 
    # cd /var/lib/ldap
    # db4.2_stat -m (Debian)
    # db_stat -m (Fedora)
 
这样可以显示完整的缓存统计信息。
 
 
讨论
 
cachesize 定义了 LDAP 后端保留在内存中的条目数量。为了获得最佳性能,这个数字应等于目录中的条目数,但是可以稍微少一点。这并不是 BDB 缓存,而是 OpenLDAP 自己的内部缓存。默认值为 1000。
 
注意你的磁盘 I/O —— iostat 是一个很好的查看工具——还要留意 Requested pages found in the cache 值,该值可以通过在数据库目录中运行 db_stat -m 获得。你应该让它尽可能地接近 100%,而从缓存之外读取的页面应该为 0。如果这个比率降到 95% 以下,就要调高 set_cachesize 值。你想让请求尽可能多地从内存缓存响应,而不想产生太多磁盘抖动。
 
set_cachesize 有三个字段:、 和 。如果你想要创建一个 2 GB 的缓存,它看上去像 set_cachesize 2 0 0。你可以通过组合 GB 和字节数值进行设置。最大值为 4 GB。不要把你的缓存设为比整个系统内存更大。任何小于 500 MB 的缓存尺寸都会自动增加 25%,以满足缓冲区开销。
 
ncache 告诉 BDB,它是否应该使用一个连续的内存区域,还是多个内存区域。0 或者 1 表示一段,一个较大的数值表示创建这么多数量的内存段。现在的 Linux 内核在 32 位 x86 系统中支持每个用户进程 1-3 GB 内存,而且别忘了内核本身也需要相当大的一块内存。这个例子将一个 2 GB 缓存设为横跨两个内存段:
 
     set_cachesize 2 0 2
     
在 64 位系统中,理论上你的整个内存空间,除了内核保留的部分之外,都可以由一个单独的进程使用。
 
创建一个太大的 set_cachesize 值可能会影响整个系统的性能,但是它不会影响 OpenLDAP,所以你可以设置一个很大的值,只要你有足够的内存即可。如果你需要节省使用内存,那么不妨查看参阅部分,获取关于细化计算的详细资料。
 
set_lk_max_locks、set_lk_max_lockers 和 set_lk_max_objects 相应地设置了 locks、lockers 和 locked objects 的最大值。如果这些值太小,请求锁就会失败。如果这些值过大,那么锁定子系统就会比实际需求使用更多的资源。大一些的数值比较安全。在数据库目录中运行 db4.2_stat -c(Fedora 上是 db_stat -c),对其密切关注。
 
锁定子系统会保持读写有序。任何写入 BDB 的东西都会得到该写入对象的互斥锁。而读是共享的。
 
配置日志记录也会影响性能。这里是相关例子的含义:
 
set_lg_regionmax
    用于数据库文件缓存的最大内存缓存字节数。应该随着数据库文件数量的提升而增加这个值。每一个为索引而配置的属性,都使用一个文件来保存索引,此外 id2entry 和 dn2id 会一直存在。
    
set_lg_bsize
    日志数据的内存缓存大小字节数。当缓存填满时,它就会被写入磁盘。
    
set_lg_max
    日志文件的最大字节数。当它达到上限时,文件就会轮转。这里应该至少设为 set_lg_bsize 的四倍。
    
set_lg_dir
    日志文件目录。为了获得最佳性能,应该在一块单独的磁盘或者远程网络共享上存储日志文件。
    
slapd -V
    提供 OpenLDAP 服务器版本号。
    
 
参阅
 
 • OpenLDAP 性能优化:
    http://www.openldap.org/faq/data/cache/190.html
 
 • Berkeley DB 入门:
    http://www.oracle.com/technology/documentation/berkeley-db/db/gsg/C/index.html
    
 • 《Berkeley DB XML 事务处理入门》第 4 章(http://www.oracle.com/technology/documentation/berkeley-db/xml/gsg_xml_txn/java/blocking_deadlocks.html),见“Locks, Blocks, and Deadlocks”部分。
 
 
12.12 配置 OpenLDAP 日志记录
 
问题
 
默认安装的 OpenLDAP 会将日志导出到 syslog,而你想让它记录自己单独的日志文件。你该怎么做?
 
 
解决方案
 
首先,我们创建一个单独的目录,以及一个空的日志文件:
 
    # mkdir /var/log/openldap
    # touch /var/log/openldap/ldap.log
 
然后,添加这几行到 /etc/syslog.conf:
 
    #Logging for openldap
    local4.* /var/log/openldap/ldap.log
 
还要在 slapd.conf 中设置你想要的日志等级,位于 Global 部分:
 
    loglevel    256
    
现在,重启 OpenLDAP 和 syslog 守护进程:
 
    # /etc/init.d/slapd restart (Debian)
    # /etc/init.d/ldap restart (Fedora)
    # /etc/init.d/sysklogd restart (Debian)
    # /etc/init.d/syslog restart (Fedora)
    
进行搜索以产生一些活动,然后查看你的日志文件。它里面应该都是这样的条目:
 
    May 22 11:53:32 xena slapd[7686]: conn=5 fd=11 ACCEPT from IP=127.0.0.1:33643 (IP=0.
    0.0.0:389)
    May 22 11:53:32 xena slapd[7686]: conn=5 op=0 BIND dn="" method=128
    May 22 11:53:32 xena slapd[7686]: conn=5 op=0 RESULT tag=97 err=0 text=
    May 22 11:53:32 xena slapd[7686]: conn=5 op=1 SRCH base="dc=alrac,dc=net" scope=2
    deref=0 filter="(objectClass=*)"
 
 
 
    12.13 备份和恢复你的目录
    12.14 细化访问控制
    12.15 变更密码

原创粉丝点击