OpenLDAP学习笔记

LDAP协议

 

      目录是一组具有类似属性、以一定逻辑和层次组合的信息。常见的例子是通讯簿,由以字母顺序排列的名字、地址和电话号码组成。
目录服务是一种在分布式环境中发现目标的方法。目录具有两个主要组成部分:

 

  • 第一部分是数据库,数据库是分布式的,且拥有一个描述数据的规划。
  • 第二部分则是访问和处理数据的各种协议。

      目录服务其实也是一种数据库系统,只是这种数据库是一种树形结构,而不是通常使用的关系数据库。目录服务与关系数据库之间的主要区别在于:二者都允许对存储数据进行访问,只是目录主要用于读取,其查询的效率很高,而关系数据库则是为读写而设计的。
提示:目录服务不适于进行频繁的更新,属于典型的分布式结构。
      LDAP是一个目录服务协议,目前存在众多版本的LDAP,而最常见的则是V2和V3两个版本,它们分别于1995年和1997年首次发布。

LDAP的基本模型


      LDAP的基本模型是建立在“条目”(Entry)的基础上。一个条目是一个或多个属性的集合,并且具有一个全局唯一的“可区分名称”(用dn表示)。与关系型数据(后面简称数据库)进行类比,一个条目相当于数据库中的一条记录,而dn相当于数据库中记录的关键字,属性相当于数据库中的字段。
提示:dn必须是全局唯一的。
      LDAP中,将数据组织成一个树形结构,这与现实生活中的很多数据结构可以对应起来,而不像设计关系型数据库的表,需要进行多种变化。例如,图1-1所示就是一个树形结构的数据。

OpenLDAP学习笔记_第1张图片

 

      在图1-1所示的树形结构中,树的根结点是一个组织的域名(dlw.com),其下分为3个部分,分别是managers、people和group,可将这3个组看作组织中的3个部门,如managers用来管理所有管理人员,people用来管理登录系统的用户,group用来管理系统中的用户组。当然,在该图中还可继续增加其他分支。
      对于图1-1所示的树形结构,使用关系数据库来保存数据的话,需要设置多个表,一层一层分别保存,当需要查找某个信息时,再逐层进行查询,最终得到结果。
      若使用目录来保存该图中的数据,则更直观。图中每个结点用一个条目来保存,不同类型的结点需要保存的数据可能不同,在LDAP中通过一个称为objectClass的类型来控制不同结点需要的数据(称为属性)。
      对于目录中的数据怎样进行引用呢?前面提到过,每一个条目都有一个dn,因为dn是唯一的,因此就可找到需要结点的数据。dn的构造方式如下:
      首先得到条目自己的名称(rdn,称为相对dn),然后开始向上逐级查找父结点,一直到根项为止。例如,对于图1-1中最右下方的结点,其dn为:

dn: cn=ldap, ou=group, o=dlw.com
 

      通过这样的方式,即可唯一标识每一个结点。
      在现实生活中,有很多这种树形结构的数据,如计算机文件系统的目录结构、Internet中的域名等。这些类型的数据,只要不需要频繁的更新,都适合用目录来保存。

LDAP的功能


在LDAP的功能模型中定义了一系列利用LDAP协议的操作,主要包含以下4部分:

 

  • 查询操作 :允许查询目录和取得数据,其查询性能比关系数据库好。
  • 更新操作 :目录的更新操作没关系数据库方便,更新性能较差,但也同样允许进行添加、删除、修改等操作。
  • 复制操作 :前面也提到过,LDAP是一种典型的分布式结构,提供复制操作,可将主服务器的数据的更新复制到设置的从服务器中。
  • 认证和管理操作 :允许客户端在目录中识别自己,并且能够控制一个会话的性质。

 

LDAP协议的特点

 

  • LDAP是一种目录服务,保存在特殊的数据库中,数据的读取速度远高于写入速度。
  • LDAP对查询做了优化,读取速度优于普通关系数据库。
  • LDAP不支持事务、不能进行回滚,需要进行这些操作的应用只有选择关系数据库。
  • LDAP采用服务器/客户端模式,支持分布式结构。
  • LDAP中的条目以树形结构组织和存储。
  • LDAP基于Internet协议,直接运行在简单和通用的TCP/IP或其他可靠的传输协议层上,使连接的建立和包的处理简单、快捷,对于互联网和企业网应用都很方便。
  • LDAP协议简单,通过使用查找操作实现列表操作和读操作。
  • LDAP通过引用机制实现分布式访问,通过客户端API实现分布式操作(对于应用透明),平衡了负载。
  • LDAP实现具有低费用、易配置和易管理的特点,并提供了满足应用程序对目录服务所需求的特性。

 

安装OpenLDAP


      在RHEL 5的安装光盘中提供了OpenLDAP 2.3.27软件包,通过OpenLDAP软件可实现LDAP服务。OpenLDAP程序包括客户端、服务器、开发工具包等软件包,本节将介绍安装这些程序包的具体过程。

 

      可以先通过rpm命令查询系统中是否已安装OpenLDAP服务器程序,若未安装该服务器程序,再使用rpm命令从RHEL光盘中安装该程序。
从RHEL 5安装光盘中找到OpenLDAP服务器程序,并安装到当前系统中。
具体操作步骤如下:
(1)在进行安装以前,首先使用以下命令创建管理OpenLDAP的用户和组。

 

# groupadd ldap
# useradd -g ldap ldap
# passwd ldap
 

(2)执行以下命令,查询系统中是否已安装openldap-servers程序。

 

# rpm -qa openldap-servers

 若无任何输出,则表示当前系统中未安装openldap-servers服务器程序。

 

(3)使用以下命令将RHEL安装光盘挂载到系统中:

 

# mount /dev/cdrom /mnt/cdrom
 

(4)执行以下命令安装openldap-servers程序的依赖程序包libtools-ltdl:

 

# rpm -ivh /mnt/cdrom/Server/libtool-ltdl-1.5.22-6.1.i386.rpm

 若不执行上面的命令,直接执行下一步的安装命令,将提示有依赖程序未安装。

 

(5)执行以下命令安装openldap-servers程序:

 

# rpm -ivh /mnt/cdrom/Server/openldap-servers-2.3.27-5.i386.rpm
 

这样就将openldap-servers服务器程序安装到系统中了。整个安装过程如下图所示。

 

OpenLDAP学习笔记_第2张图片

 

(6)使用以下命令修改保存数据的目录/var/lib/ldap/及其文件的所有者,并修改权限,只有ldap用户才对数据有读写权限:

 

# chown ldap.ldap /var/lib/ldap
# chmod -R 600 /var/lib/ldap
 

在光盘中还有以下与openldap有关的软件包,也可使用类似命令进行安装,这里不再逐个介绍。
  ● openldap-clients-2.3.27-5.i386.rpm:客户端操作的相关程序。
  ● openldap-devel-2.3.27-5.i386.rpm:开发包。


测试安装正确性


      安装完成后,将在/var/lib/目录中创建一个子目录ldap来保存数据,同时在/etc/目录中也将创建一个子目录openldap来保存配置文件。而openldap的守护进程slapd则保存在/usr/bin/目录中。
提示:如果是通过源代码进行编译安装的openldap,这些程序文件放置的位置可能不同。

1.启动服务进程
      要检查安装是否正确,可直接运行守护进程,这里将使用默认的配置。
      启动OpenLDAP服务器可使用以下命令之一:

 

# server ldap start
# /etc/rc.d/init.d/ldap
# /usr/sbin/slapd
 

使用第1条命令来启动ldap服务进程的过程如下图所示。

 

OpenLDAP学习笔记_第3张图片

 

提示:使用/usr/sbin/slapd命令启动服务程序是最好的一种方式,如果用前两条命令启动openldap服务程序失败,可使用最后一条命令试一下。

 

      从上图可看出,启动的是slapd进程,并有一个提示信息,提示没有DB_CONFIG文件。可通过以下命令将DB_CONFIG文件复制到/var/lib/ldap/目录中:

 

# cp /etc/openldap/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
 

另外,由于使用的是默认配置文件,提示希望使用后缀“dc=my-domain, dc=com”。下节将介绍修改配置文件的操作。

 

2.查看监听端口
      OpenLDAP使用的监听端口是389,通过netstat命令查看该端口是否处于监听状态,可了解slapd进程是否在工作。具体命令如下:

 

# netstat –tnlp | grep 389
 

执行结果如下图所示,可以看出,389端口处于监听状态,表示slapd进程正在工作。

 

 

3.搜索测试
      slapd服务进程启动后,可使用OpenLDAP客户端的一个搜索命令进行一次搜索,以检查服务的配置是否正确。
      使用以下命令进行搜索:

 

# ldapsearch -x -b '' -s base '(objectclass=*)'
 

注意:-b后面是两个单引号,用来阻止特殊字符被Shell解析。

 

      由于还未向LDAP服务器中添加任何数据,因此,系统中应该只有“根”这个条目,执行以上搜索的结果如下图所示。

OpenLDAP学习笔记_第4张图片

 

从以上测试可看出,OpenLDAP已经正确安装到系统中,接下来就需要修改配置文件,设置LDAP的根目录了。

 

 

配置OpenLDAP

 

      在上面的例子中的搜索结果可看出,在配置文件中是以默认的“dc=my-domain, dc=com”作为后缀,需要对其进行修改,当然也还需要修改其他的一些配置。下面将介绍对配置文件的修改操作。

slapd.conf


      OpenLDAP的配置文件位于/etc/openldap/目录中,名称为slapd.conf。该文件内容较多,通常只需要修改几个地方即可,包括修改后缀、管理员及其密码。其初始内容如下:

 

#######################################################################
# ldbm and/or bdb database definitions
#######################################################################

database        bdb
suffix          "dc=my-domain,dc=com"
rootdn          "cn=Manager,dc=my-domain,dc=com"
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
# rootpw                secret
# rootpw                {crypt}ijFYNcSNctBYg
 

其中各语句的含义如下:
  ● 以符号“#”开始的行是注释行,第1~3行、第8~12行都是。
  ● 第5行设置数据库,可使用ldbm或bdb。
  ● 第6行设置后缀。
  ● 第7行设置超级管理员的名称,与Linux系统中的root类似。在配置时用该用户,配置完成后,建议将其删除。
  ● 第11行设置超级管理员的密码,默认状态是被注释了的。这行的密码是明文状态。
  ● 第12行也是设置超级管理员的密码,这行是以加密方式设置的(默认状态也是被注释了的)。
根据实际情况,修改第6、7、11行即可,具体如下:

#######################################################################
# ldbm and/or bdb database definitions
#######################################################################

database        bdb
suffix          "dc=dlw,dc=com"
rootdn          "cn=root,dc=dlw,dc=com"
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw  secret
# rootpw  {crypt}ijFYNcSNctBYg
 

      以上内容中,第6行将后缀修改为“dc=dlw,dc=com”,同时第7行的超级管理员的后缀部分也需要随之修改。将第11行的注释取消,设置超级管理员的密码为MD5密码secret。
      修改密码时需要注意rootpw前面不要有空格,以及rootpw与密码之间使用Tab键分割。
      经过以上修改,保存后退出,接着使用以下命令重启slapd进程:

 

# service ldap restart
 

了解schema


      对于LDAP目录中保存的信息,可以使用LDIF(LDAP Interchange Format)格式来保存。这是一种标准文本文件格式,使用这种格式保存得的LDAP服务器数据库中的数据可方便读取和修改,这也是其他大多数服务配置文件所采取的格式。
      LDIF文件常用来向目录导入或更改记录信息,这些信息需要按照LDAP中schema的格式进行组织,并会接受schema的检查,不符合其要求的格式将会出现报错信息。有关LDIF文件的格式和创建将在第4章进行介绍,这里简单介绍一下组织LDAP数据格式的schema文件。
      在LDAP中,schema用来指定一个目录中所包含的对象(objects)的类型(objectClass),以及每一个类型(objectClass)中必须提供的属性(Atrribute)和可选的属性。可将schema理解为面向对象程序设计中的类,通过类定义一个具体的对象。LDIF中的数据条目可理解为是一个具体的对象,是通过schema来规划创建的。因此,schema是一个数据模型,用来决定数据按什么方式存储,并定义存储在不同的条目(Entry)下的数据之间的关系。schema需要在主配置文件slapd.conf中指定,以用来决定在目录中可以使用哪些objectClass。
      在/etc/openldap/schema/目录中提供了许多schema文件,只需要在配置文件slapd.conf中使用include命令将需要使用的schema包含即可。例如,配置文件默认包含了以下schema文件:

 

写道
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
 

提示:通常使用系统提供的schema就可解决大部分应用。管理员也可以自己设计制定schema,一般包括属性定义(AttributeDefinition)、类定义(ClassDefinition)以及语法定义(SyntaxDefinition)等部分。这里就不介绍具体的设计方法了。

 

管理OpenLDAP


      启动OpenLDAP服务器程序之后,接下来的操作就是通过客户端程序对目录进行操作,包括添加、修改、删除和搜索数据等操作。能对LDAP进行操作的客户端程序很多,下面简单介绍在Linux命令方式下进行这些操作的方法。

 

向目录数据库中添加数据


      初始状态下,LDAP是一个空目录,即没有任何数据。可通过程序代码向目录数据库中添加数据,也可使用OpenLDAP客户端工具ldapadd命令来完成添加数据的操作,该命令可将一个LDIF文件中的条目添加到目录。因此,需要首先创建一个LDIF文件,然后再进行添加操作。

 

1.LDIF文本条目格式

 

      LDIF用文本格式表示目录数据库的信息,以方便用户创建、阅读和修改。在LDIF文件中,一个条目的基本格式如下:

写道
# 注释
dn: 条目名
属性描述: 值
属性描述: 值
属性描述: 值
... ...
 

      dn行类似于关系数据库中一条记录的关键字,不能与其他dn重复。一个LDIF文件中可以包含多个条目,每个条目之间用一个空行分隔。
      例如,以下内容组成一个条目:

写道
1: dn: dc=dlw, dc=com
2: objectclass: top
3: objectclass: dcobject
4: objectclass: organization
5: dc: dlw
6: o: dlw,Inc.
 

在以上文本中,各行含义如下:

 

  • 第1行的dn定义该条目的标识。
  • 第2~4行定义该条目的objectcCass,可以定义多个属性,如上面代码中定义了3个objectClass。条目的属性根据objectClass的不同而不同,有的objectClass有必须设置的属性。在2~4行的3个objectClass中,top没有必须定义的属性,dcobject必须定义属性dc,用来表示一个域名的部分,而organization必须定义属性o,用来表示一个组织的名称。
  • 根据objectClass的要求,第5、6行分别定义属性dc和属性o的值。

2.了解objectClass


      LDAP中,一个条目必须包含一个objectClass属性,且需要赋予至少一个值。每一个值将用作一条LDAP条目进行数据存储的模板;模板中包含了一个条目必须被赋值的属性和可选的属性。
      objectClass有着严格的等级之分,最顶层是top和alias。例如,organizationalPerson这个objectClass就隶属于person,而person又隶属于top。

 

      objectClass可分为以下3类:

  • 结构型(Structural) :如person和organizationUnit;
  • 辅助型(Auxiliary) :如extensibeObject;
  • 抽象型(Abstract) :如top,抽象型的objectClass不能直接使用。

在OpenLDAP的schema中定义了很多objectClass,下面列出部分常用的objectClass的名称。
  ● account
  ● alias
  ● dcobject
  ● domain
  ● ipHost
  ● organization
  ● organizationalRole
  ● organizationalUnit
  ● person
  ● organizationalPerson
  ● inetOrgPerson
  ● residentialPerson
  ● posixAccount
  ● posixGroup

 

3.了解Attribute


      属性(Attribute)类似于程序设计中的变量,可以被赋值。在OpenLDAP中声明了许多常用的Attribute(用户也可自己定义Attribute)。常见的Attribute含义如下:
  ● c:国家。
  ● cn:common name,指一个对象的名字。如果指人,需要使用其全名。
  ● dc:domain Component,常用来指一个域名的一部分。
  ● givenName:指一个人的名字,不能用来指姓。
  ● l:指一个地名,如一个城市或者其他地理区域的名字。
  ● mail:电子信箱地址。
  ● o:organizationName,指一个组织的名字。
  ● ou:organizationalUnitName,指一个组织单元的名字。
  ● sn:surname,指一个人的姓。
  ● telephoneNumber:电话号码,应该带有所在的国家的代码。
  ● uid:userid,通常指某个用户的登录名,与Linux系统中用户的uid不同。

 

提示:objectClass是一种特殊的Attribute,它包含其他用到的Attribute以及其自身。

 

      对于不同的objectClass,通常具有一些必设属性值和一些可选属性值。例如,可使用person这个objectClass来表示系统中一个用户的条目,对于系统中用户通常需要有这样一些信息:姓名、电话、密码、描述等。如下图所示,对于person,通过cn和sn设置用户的名和姓,这是必须设置的,而其他属性则是可选的。

 

OpenLDAP学习笔记_第5张图片

 

下面列出部分常用objectClass要求必设的属性。
  ● account:userid。
  ● organization:o。
  ● person:cn和sn。
  ● organizationalPerson:与person相同。
  ● organizationalRole:cn。
  ● organizationUnit:ou。
  ● posixGroup:cn、gidNumber。
  ● posixAccount:cn、gidNumber、homeDirectory、uid、uidNumber。

4.创建LDIF文件


      对以上内容有一定了解之后,就可以编写输入LDIF文件,编辑需要向目录数据库添加的条目了。
      下面根据如下图所示的结构,创建LDIF文件dlw.com.ldif。

 

OpenLDAP学习笔记_第6张图片

 

      对上图进行分析,该目录结构分为3层,有4个结点。根据上图可创建LDIF文件如下:
提示:每个结点可用一个dn表示,对于每个结点,又可继续添加新的结点。如在根结点中可添加其他部门ou,在ou=managers结点也可继续添加其他管理人员的信息。

 

写道
1: dn:dc=dlw,dc=com
2: objectclass:top
3: objectclass:dcobject
4: objectclass:organization
5: dc:dlw
6: o:dlw,Inc.
7:
8: dn:ou=managers, dc=dlw, dc=com
9: ou:managers
10: objectclass:organizationalUnit
11:
12: dn:cn=dlw,ou=managers,dc=dlw,dc=com
13: cn:dlw
14: sn:dongliwei
15: objectclass:person
16:
17: dn:cn=test,ou=managers,dc=dlw,dc=com
18: cn:test
19: sn:Test User
20: objectclass:person
 

以上文件中各行的含义如下:

 

  • 第1~6行创建根结点,这部分在前面也有介绍,就不再重复了。
  • 第7、11、16行为空行,用来分隔4个dn条目(4个结点)。
  • 第8~10行定义cn=managers结点的条目,该条目的objectClass为organizationalUnit,因此需要用ou属性定义组织名称。
  • 第12~15行定义cn=dlw结点的条目,该条目使用的objectClass为person,因此需设置cn和sn两个属性值。
  • 第17~20行与第12~15行的意义相同。

 

 

      在以上LDIF文件中,第1、8、12、17行以dn开头,这部分内容必须唯一,并且在向目录数据库添加这些数据时,也要确保这些数据不能与目录数据库中已有数据相同,否则,添加操作将中断。

 

5.从LDIF文件添加到目录数据库


      使用OpenLDAP客户端工具ldapadd命令,可将LDIF文件中的条目添加到目录数据库中,该命令的格式如下:
       ldappadd  选项  LDIF文件
      在ldappadd命令中常用的选项如下:

 

  • -x:进行简单认证。
  • -D:用来绑定服务器的dn。
  • -h:目录服务的地址。
  • -w:绑定dn的密码。
  • -f:使用LDIF文件进行条目添加的文件。

 

将前面编写的LDIF文件的条目数据添加到目录数据库中。
具体操作步骤如下:

(1)检查dlw.com.ldif文件中的内容,需要注意的是,每个冒号后面都需要空一格,而每行结束处不能留有空格字符。
(2)使用以下命令将dlw.com.ldif文件中的条目添加到目录中:

写道
# ldapadd -x -D "cn=root,dc=dlw,dc=com" -w secret -f dlw.com.ldif
 

执行以上命令,如果添加操作正常完成,将显示如下图所示的提示信息,表示添加了4个条目到目录数据库中。

 

OpenLDAP学习笔记_第7张图片

 

提示:如果以上命令执行不成功,需要逐个字符检查dlw.com.ldif文件中的内容,特别注意空格的问题。

 

查询


      添加到目录中的条目被保存在目录数据库,在Linux命令界面下,可使用OpenLDAP客户端工具ldapsearch命令来进行查询。该命令的格式如下:


      ldapsearch  选项  过滤  属性值


常用的选项有以下几个:


  ● -x:进行简单认证。
  ● -D:用来绑定服务器的dn。
  ● -w:绑定dn的密码。
  ● -b:指定要查询的根节点。
  ● -H:制定要查询的服务器。

 

使用ldapsearch命令查询“dc=dlw, dc=com”下的所有条目,可使用以下命令:

# ldapsearch -x -b "dc=dlw,dc=com"
 

执行结果如下图所示。

 

OpenLDAP学习笔记_第8张图片

 

而如果使用以下命令,将查询显示sn中以字符wu开头的条目,将得到如下图所示的查询结果,只找到一个条目。

 

# ldapsearch -x -b 'dc=dlw,dc=com' 'sn=wu*'
 

OpenLDAP学习笔记_第9张图片

 

 

修改条目


      使用OpenLDAP客户端工具ldapmodify命令可对目录数据库中的条目进行修改。该命令的格式如下:


      ldapmodify  选项


      该命令的选项也很多,常用选项与ldapadd类似,这里就不再列出了。
      提示:使用ldapmodify命令不能修改条目的dn,但可以修改其他属性值。

使用ldapmodify命令修改条目信息可以有两种方式:一种是交互式进行修改,另一种是通过文件进行修改。

1.交互式修改


      修改前面创建的条目“cn=test, ou=managers, dc=dlw, dc=com”,将其sn属性修改为“Test User Modify”,并添加一个description属性,设置其值为“add Attribute”。
      首先输入以下命令,进行修改状态:

# ldapmodify -x -D "cn=root,dc=dlw,dc=com" -W secret
 

执行以上命令后,终端将等候用户输入需要修改条目的dn,输入以下内容:

 

dn: cn=test, ou=managers, dc=dlw, dc=com
changetype: modify
replace: sn
sn: Test User Modify
 

      以上输入内容中,第1行查找需要修改的条目,第2行设置修改模式,第3行设置需要替换的属性sn,第4行给属性sn重新设置一个值,替换该属性原有的值。
      输入完以上内容之后再按Enter键,程序将按以上设置更新数据,然后按Ctrl+C键退出修改命令。执行过程如下图所示。

OpenLDAP学习笔记_第10张图片

 

使用以上命令修改条目的数据之后,可使用以下命令查看是否修改成功:

 

#ldapsearch -x -b 'dc=dlw,dc=com' 'cn=test'
 

执行以上命令查看test条目的数据如下图所示,可以看到sn属性被修改了。

 

OpenLDAP学习笔记_第11张图片

 

2.通过文件修改


    通过前面的方式对条目进行修改时,很不方便,如果在交互方式时输错了某个字符,只能中断命令后重新进行修改。因此,更好的修改方法是首先将修改时输入的文字保存到一个文件中,然后以该文件作为输入进行修改。用这种方式进行操作,首先需要创建一个临时文件,用来保存需要进行的修改操作,下面演示这种方式的修改过程。

【例子】 通过修改命令将前面LDAP数据库中的信息还原,即将sn属性由“Test User Modify”修改为“Test User”。
具体操作步骤如下:
(1)使用vi编辑器创建一个文件modify,在其中输入以下内容:

dn: cn=test,ou=managers,dc=dlw,dc=com
changetype: modify
replace: sn
sn: Test User

 从以上输入内容可看到,与在交互式时输入的内容完全相同。
技巧:使用文件方式修改条目,可方便修改和检查,若某个地方有输入错误,可修改后再调用ldapmodify进行修改,减少输入量。

(2)使用以下命令调用modify的内容进行修改:

 

# ldapmodify -x -D "cn=root,dc=dlw,dc=com" -w secret -f modify
 

执行结果如下图所示。

 

OpenLDAP学习笔记_第12张图片

 

删除条目


      对于目录数据库中不用的条目,也可使用ldapdelete命令将其删除。该命令的格式如下:


      ldapdelete  选项  删除条目


      该命令使用的选项与ldapadd类似,就不再列出来了。
      删除目录数据库中的“cn=test,ou=managers,dc=dlw,dc=com”条目,具体命令如下:

 

# ldapdelete -x -D "cn=root,dc=dlw,dc=com" -w secret \
> "cn=test,ou=managers,dc=dlw,dc=com"
 

      顺利执行以上命令后,终端上将不会有任何信息输出,表示完成了删除操作。
      使用ldapdelete命令只能删除树形结构中的叶结点条目,如果删除非叶结点条目,将出现错误提示。例如,执行以下命令删除根结点“dc=dlw,dc=com”,由于根结点下面还有结点,将显示如下图所示的错误提示信息:

 

 

# ldapdelete -x -D "cn=root,dc=dlw,dc=com" -w secret "dc=dlw,dc=com"
 

数据导出


      通过ldapadd命令可向目录数据库中添加数据,在某些情况下,可能还需要进行反向操作,即将目录数据库中的数据导出。
      使用ldapsearch命令对目录数据库进行搜索,然后通过重定向将搜索结果保存到一个文件中,可达到导出数据的目的。另外,导出数据更常用的是slapcat命令,该命令的格式如下:


      slapcat  选项


      最常用的选项就是-l,表示导出为LDIF文件格式。
      如将本章前面例子中创建的目录数据库导出为export.ldif文件,可使用以下命令:

 

#slapcat -l export.ldif
 

      执行以上命令将在当前工作目录得到文件export.ldif,打开文件将显示如下图所示的内容:

 

OpenLDAP学习笔记_第13张图片

 

提示:从导出结果可看出,除了使用ldapadd命令添加到目录数据库中的条目数据外,还导出了很多其他信息,包括条目录UUID、时间戳等信息。

 

 

设置主从LDAP服务器


      在某些时候,为了对LDAP服务器进行负载均衡,可能希望设置多台LDAP服务器。对于设置多台LDAP服务器的关键问题是数据的同步问题,使用slurpd进程可进行主LDAP服务器向从LDAP服务器复制数据的操作。下面将介绍架设主从LDAP服务器的过程。

 

多台LDAP服务器工作过程


      对于多台LDAP服务器,可设置一台为主服务器,其他的为从服务器。本节介绍一台从服务器的配置,若是多台从服务器也可按此步骤进行操作。
注意:在进行配置之前应首先确保每个LDAP服务器都已安装好OpenLDAP服务器程序,并能正确工作。
      通过本节下面介绍的方法配置好主从LDAP服务器之后,在主服务器运行slurpd进程,该进程使用LDAP协议从主服务器的数据库更新从服务器的数据,具体操作过程如下:


(1)LDAP客户端向从服务器提交一个LDAP修改请求。
(2)从服务器给LDAP客户端返回一个指向主服务器的引用。
(3)LDAP客户端向主服务器提交LDAP修改请求。
(4)主服务器对数据库中的数据进行修改,并将改变写入本机的日志文件。
(5)在主服务器运行的slurpd进程检查到日志中有新内容,通过日志的信息将改变发送给从服务器。
(6)从服务器接收slurpd发来的信息,对本地数据进行修改。


      以上过程就是使用slurpd进程进行数据复制的过程。从以上过程可看出,需要在主服务器的配置文件中设置要向哪些从服务器发送复制信息、主服务器还要设置一个记录数据改变的日志文件,而从服务器需要设置一个指向主服务器的链接。

复制数据库


首先,把主从服务器关闭。通过以下三步操作静态同步主从服务器上的数据:

 

  • 把主服务器上/var/lib/ldap目录下的所有数据库文件全部拷贝到从服务器的同目录中,覆盖原有文件。
  • 把主服务器上的/etc/ldap/schema目录下的所有schema文件拷贝到从服务器的同目录中,覆盖原有文件。
  • 把主服务器上/etc/ldap/slapd.conf文件拷贝到从服务器的同目录中,覆盖原有文件。

 

设置主服务器


配置主服务器上的slapd.conf文件,取消replogfile指令前的注释符号,取消后的结果如下:

# Replicas of this database
replogfile      /var/lib/ldap/replog
 

增加replica指令,如:

 

#replace config
replica uri=ldap://192.168.14.21:389     #指定从服务器主机名和端口号
binddn="cn=root,dc=dlw,dc=com"         #指定需同步的DN的管理员
bindmethod=simple credentials=111111  #指定验证方式和需同步的DN的管理员密码
 

设置从服务器


配置从服务器上的slapd.conf文件,增加updatedn指令,如:

 

updatedn " cn=root,dc=dlw,dc=com"          #与主服务器的binddn对应
 

在从服务器的配置文件中,不要包含replica和replogfile指令。


测试主从LDAP服务器


经过以上步骤的操作,主从LDAP服务器都已准备好,接下来就可以测试相关操作。


   1.启动主LDAP服务器
        在主LDAP服务器中启动slapd进程和slurpd进程。
   2.启动从LDAP服务器
        在主LDAP服务器中启动slapd进程。


【例子】测试主从LDAP服务器。
具体操作步骤如下:

(1)在主LDAP服务器中使用以下命令修改一个条目:

 

#ldapmodify -x -D "cn=root,dc=dlw,dc=com" -w secret
 

输入以下内容,修改cn=dlw条目的内容:

 

dn: cn=dlw,ou=managers,dc=dlw,dc=com
changetype: modify
replace: sn
sn: dongliwei
 

输入后按Enter键完成修改,操作过程如图5-7所示(将sn修改为dongliwei)。

 

OpenLDAP学习笔记_第14张图片

 

(2)在从LDAP服务器中进行操作,查看主LDAP服务器中的操作是否被复制到从LDAP服务器中来了。在从LDAP服务器中使用以下命令进行查询:

 

#ldapsearch -x -b "dc=dlw,dc=com" "cn=dlw"
 

执行结果如下图所示,从图中可看到其中的sn也被修改为dongliwei了(数据库中原来的内容为zhangsan.modi,是前面例子中修改的值),即被主LDAP服务器进行了同步复制。

 

OpenLDAP学习笔记_第15张图片

 

 

OpenLDAP在用户认证的应用


      OpenLDAP经常用在用户登录认证方面,通过LDAP的数据复制功能,可让用户使用一个账户登录网络中使用LDAP服务的所有服务器。在主LDAP服务器中设置好用户账户数据,然后通过在网络中的任意客户端都可使用设置的账号进行登录操作。下面将简单介绍将用户认证迁移到LDAP的操作方法。

用户认证用到的ojbectClass


      在LDAP中用来保存用户认证条目的objectClass主要有以下3个,分别用来保存组、用户、密码等信息到目录的条目中。

  • posixGroup:可设置属性cn、userPassword、gidNumber等。
  • posixAccount:可设置属性cn、gidNumber、uid、uidNumber、homeDirectory、loginShell等。
  • shadowAccount:可设置属性uid、shadowExpire、shadowFlag、shadowInactive、shadowLastChange、shadowMax、shadowMin、shadowWarning、userPassword等。

提示:从上面列出的属性的名称可以很容易地与组、用户的相关信息联系起来。

 

使用迁移工具


      要使用LDAP进行用户认证,首先应该考虑的就是数据迁移的工作量。如果要操作员从/etc/passwd和/etc/group文件中逐个将信息重新录入,工作量将非常大。
      OpenLDAP为用户考虑到了这些迁移工作,提供了多个迁移工具的脚本程序,这些程序位于/usr/share/openldap/migration/目录中,在该目录中有很多扩展名为pl和sh的脚本文件,通过这些迁移工具,可以很方便地将系统中的用户迁移到LDAP目录数据库中。下面介绍具体的迁移步骤。

【例子】 将系统中的用户信息迁移到LDAP目录数据库中。
具体操作步骤如下:
(1)修改/usr/share/openldap/migration/migrate_common.ph文件,在其中查找以下内容:

$DEFAULT_BASE="dc=padl,dc=com";
 

将其修改为目录服务器使用的根,如本章使用的例子要改为以下形式:

 

$DEFAULT_BASE="dc=dlw,dc=com";
 

保存后退出。

 

 

(2)使用以下命令执行脚本migrate_base.pl,用来创建根项,并为Hosts、Networks、Group和People等创建低一级的组织单元(执行该命令将生成base.ldif文件):

 

#./migrate_base.pl > base.ldif
 

(3)由于本章前面已在LDAP服务器中创建了根项“dc=dlw,dc=com”,因此将base.ldif文件中的第1个条目删除,另外,在用户认证中只用到组和用户,也将其他无关条目删除,只保存以下内容(例子):

 

dn: ou=People,dc=dlw,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit

dn: ou=Group,dc=dlw,dc=com
ou: Group
objectClass: top
objectClass: organizationalUnit
 

(4)使用以下命令将base.ldif文件中的条目导入目录数据库:

 

# ldapadd -x -D "cn=root,dc=dlw,dc=com" -w secret -f  base.ldif
 

执行结果如下图所示。

 

 

(5)开始迁移组信息。使用以下命令将/etc/group中的组信息保存到临时文件group.tmp中:

 

#cat /etc/group > group.tmp
 

(6)系统组不导入LDAP目录数据库中,因此需对group.tmp文件中的信息进行编辑,只保留需要导入LDAP目录数据库的组的信息。


(7)使用以下命令将组的数据生成LDIF条目信息:

#./migrate_group.pl group.tmp > group.ldif
 

(8)使用cat命令查看group.ldif的内容,可看到已按posixGroup这种objectClass将组的数据组织完成,如下图所示。

 

OpenLDAP学习笔记_第16张图片

 

(9)类似地,使用以下命令导出/etc/passwd中的用户数据,并删除不需要的用户,然后使用migrate_passwd.pl脚本生成LDIF文件:

 

#cat /etc/passwd > passwd.tmp
#./migrate_passwd.pl passwd.tmp > passwd.ldif
#cat passwd.ldif
 

提示:从上面列出的属性的名称可以很容易地与组、用户的相关信息联系起来。

 

(10)使用以下命令将组和用户信息导入目录数据库:

 

#ldapadd -x -D "cn=root,dc=dlw,dc=com" -w 111111 -f group.ldif
#ldapadd -x -D "cn=root,dc=dlw,dc=com" -w 111111 -f passwd.ldif
 

执行以上命令的过程如下图所示。

 

OpenLDAP学习笔记_第17张图片

 

(11)使用以下命令查看目录数据库中用户root的信息,用“uid=root”作查询条件:

 

#ldapsearch -x -b 'dc=dlw,dc=com' 'uid=root'
 

查找结果如下图所示。

 

OpenLDAP学习笔记_第18张图片

 

      通过以上的操作,就将需要导入的组和用户的信息导入到了目录数据库中,接下来还需要对客户端进行设置,使用LDAP进行登录验证操作。

 

 

设置客户端登录


若客户端要使用LDAP进行用户登录认证,则可使用本地计算机中不存在的用户名进行登录操作。
【例子】 修改配置文件,设置客户端使用LDAP进行认证。
具体操作步骤如下:
(1)修改客户端计算机中的/etc/sysconfig/authconfig文件,将以下项都修改为yes:

 

USELDAP=yes
USELDAPAUTH=yes
USEMD5=no
USESHADOW=yes
USELOCAUTHORIZE=yes
 

(2)修改客户端计算机中的/etc/openldap/ldap.conf文件,修改内容如下:

 

host 192.168.14.20
BASE dc=dlw,dc=com
ssl off
 

(3)修改客户端计算机中的/etc/nsswitch.conf文件,在passwd、shadow、group后面都加上ldap,如下图所示。

 

OpenLDAP学习笔记_第19张图片

 

      经过以上配置以后,在客户端就可以使用LDAP目录数据库中的用户信息在客户端进行登录操作了。登录操作与使用本地用户账号相同,这里就不再演示了。

 

 

LDAP Schema


      Schema是LDAP的一个重要组成部分,类似于数据库的模式定义,LDAP的Schema定义了LDAP目录所应遵循的结构和规则,比如一个 objectclass会有哪些属性,这些属性又是什么结构等等,schema给LDAP服务器提供了LDAP目录中类别,属性等信息的识别方式,让这些可以被LDAP服务器识别。
在LDAP的schema中,有四个重要的元素:

    Objectclass
    objectclass定义了一个类别,这个类别会被不同的目录(在LDAP中就是一个Entry)用到,它说明了该目录应该有哪些属性,哪些属性是必须的,哪些又是可选的。一个objectclass的定义包括名称(NAME),说明(DESC),类型(STRUCTURAL或AUXILARY ,表示是结构型的还是辅助型的),必须属性(MUST),可选属性(MAY)等信息。

Objectclass格式:
objectclass = ( whsp
numericoid whsp //全局唯一的 OID
[ "NAME" qdescrs ] //类名称
[ "DESC" qdstring ] //类描述
[ "OBSOLETE" whsp ]
[ "SUP" oids ] ; //父类
[ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
[ "MUST" oids ] ; //必填属性集合
[ "MAY" oids ] //选填属性集合
whsp ")"
 

例如:

 

# Object Class Definitions 
objectclass ( 1.3.6.1.4.1.7914.1.2.2.1 NAME 'kunmailUser' 
DESC 'KunMail-LDAP User' 
SUP top 
STRUCTURAL
MUST(username$cn$vuid$vgid)
MAY(maildir$home$clearpw$forwardAddr$quota$storeHost$delivery$mailReplyText$active))
 

      这里kunmailUser这种数据,要包含maildir $ home $ clearpw $ forwardAddr $ quota $ storeHost $ delivery $ mailReplyText $ active等可选项,还要包括username $ cn $ vuid $ vgid 必选项。 可选项用MAY()来包含,必选项用MUST()来包含。DESC是说明项。SUP表示父类(有点像面向对象编程啊)top表示没有父类,他自己是顶级。STRUCTURAL是存储方式。一般来说每个节点都要包含一个ABSTRACT类("top" or "alias"), 至少一个STRUCTURAL类,0个或者多个AUXILIARY类。AUXILIARY表示辅助型、STRUCTURAL表示结构型(默认)、ABSTRACT表示摘要型。
      下面定义一个允许将myPhoto增加到任何已经存在的条目中的auxiliary对象类:

objectclass= ( 1.1.2.2.1 NAME 'myPhotoObject'
DESC 'mixin myPhoto'
AUXILIARY
MAY myPhoto )
 

      如果您的组织需要一个私有的结构化对象类来表示用户,你可以子类化任何一个已经存在的person类,比如inetOrgPerson(RFC2798),然后增加需要的属性:

 

objectclass =( 1.1.2.2.2 NAME 'myPerson'
DESC 'my person'
SUP inetOrgPerson
MUST ( 'myUniqueName' $ 'givenName' )
MAY 'myPhoto' )
 

      该对象类从inetOrgPerson中继承允许的或者必须的属性,但是,要求myUniqueName和givenName,允许myPhoto。

 

 

Attribute


      attribute就是一个上面objectclass中可能包含的属性,对其的定义包括名称,数据类型,单值还是多值以及匹配规则等。后面用具体的例子来说明。

 

Attribute格式:

 

attributeType ( whsp
numericoid whsp //全局唯一的 OID
[ "NAME" qdescrs ] //属性名称
[ "DESC" qdstring ] //属性描述
[ "OBSOLETE" whsp ]
[ "SUP" woid ] //本属性从其它属性中派生出来的
[ "EQUALITY" woid //相等性匹配
[ "ORDERING" woid//顺序匹配
[ "SUBSTR" woid ] //字符串匹配
[ "SYNTAX" whsp noidlen whsp ] //字段的数据类型的OID
[ "SINGLE-VALUE" whsp ] //定义本属性为单值(默认多值)
[ "COLLECTIVE" whsp ] //default not collective
[ "NO-USER-MODIFICATION" whsp ]//default user modifiable
[ "USAGE" whsp AttributeUsage ]//default userApplications
whsp ")"
AttributeUsage =
"userApplications" /
"directoryOperation" /
"distributedOperation" / ; DSA-shared
 

whsp是空格的意思(' ')。numericoid 是全局唯一的 OID,是带.的十进制形式 (e.g. 1.1.0), qdescrs有一个或几个意思, woid 可以使名称或者是 OID 可选择的一定长度的后缀(e.g {10})。
例如,属性类型name和cn在core.schema中如下定义:

attributeType ( 2.5.4.41 NAME 'name'
DESC 'name(s) associated with the object'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
attributeType ( 2.5.4.3 NAME ( 'cn' $ 'commonName' )
DESC 'common name(s) assciated with the object'
SUP name )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.6 NAME 'quota' 
DESC 'The amount of space the user can use until all further messages get bounced.' 
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 
SINGLE-value ) 
 

请注意,每一个都定义了属性的OID,给出了一个短的名称,以及一个简短的描述。每一个名称都是OID的一个别名。Slapd(8)在返回结果的时候,将返回第1个列出的名称。
      第1个名称,name,保存了directoryString(UTF-8编码的Unicode)语法。该语法由OID说明。(1.3.6.1.4.1.1466.115.121.1.15标识了目录字符串语法)。还说明了一个推荐长度为32768的选项。服务器应该支持该长度的值,但是,也可以支持更长的值。该域没有指明长度限制,因此,在服务器上被忽略,并且服务器不会限制其大小。另外,相等和子串匹配使用不区分大小写的规则。下面是经常使用的语法和匹配规则(OpenLDAP支持这些,以及更多)
      第2个属性,cn,是name的一个子类型,因此,它继承了语法,匹配规则,并且使用name.commonName作为别名。
      两个属性都没有限制到单一值。都可以被用户应用程序所使用,都不存在过期,都不是集合。
      很多组织为用户保留唯一的名字(unique name),虽然用户可以使用displayName,但是这个属性(name)依旧由用户控制。而不是organization。我们可以从 inetorgperson.schema 拷贝displayName ,替换OID,name,和描述(description)。

attributetype ( 1.1.2.1.1 NAME 'myUniqueName'
DESC 'unique name with my organization'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
 

但是,如果我们要使name属性包含一个断言,这个属性可以被定义为name的子属性。

 

attributetype ( 1.1.2.1.1 NAME 'myUniqueName'
DESC 'unique name with my organization'
SUP name )
 

      很多的组织为每一个用户保留一个头像。myPhoto属性类型的定义可以用来保存用户的头像。当然用户可以选择jpegPhoto属性类型(RFC2798)(或其子类型)来保存头像。当然你只能在图片符合JPEG File Interchange Format时使用。
      当然,一个使用八进制语法的属性类型可以这样的定义:

 

attributetype ( 1.1.2.1.2 NAME 'myPhoto'
DESC 'a photo (application defined format)'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
SINGLE-VALUE )
 

      在这,语法中并没有置顶photo的格式(format),这里假设访问属性的应用可以对其值进行处理。
      如果你想支持多种图片格式,你需要为每一个格式定义属性类型。为图片添加类型信息的前缀。或者使用ASN.1描述值,和use the ;binary transfer option。
      可以使图片属性能够保存URI,你可以在labeledURI(RFC2079)后创建一个属性,或者创建一个子类型。

 

attributetype ( 1.1.2.1.3 NAME 'myPhotoURI'
DESC 'URI and optional label referring to a photo'
SUP labeledURI )
 

Syntax


      syntax是LDAP中的“语法”,其实就是LDAP中会用到的数据类型和数据约束,这个语法是遵从X.500中数据约束的定义的。其定义需要有一个ID(遵从X.500)以及说明(DESP)

 

 

Commonly Used Syntaxes

Name

OID

Description

boolean

1.3.6 .1.4.1.1466.115.121.1.7

boolean value

distinguishedName

1.3.6 .1.4.1.1466.115.121.1.12

DN

directoryString

1.3.6 .1.4.1.1466.115.121.1.15

UTF-8 string

IA5String

1.3.6 .1.4.1.1466.115.121.1.26

ASCII string

Integer

1.3.6 .1.4.1.1466.115.121.1.27

integer

Name and Optional UID

1.3.6 .1.4.1.1466.115.121.1.34

DN plus UID

Numeric String

1.3.6 .1.4.1.1466.115.121.1.36

numeric string

OID

1.3.6 .1.4.1.1466.115.121.1.38

object identifier

Octet String

1.3.6 .1.4.1.1466.115.121.1.40

arbitary octets

Printable String

1.3.6 .1.4.1.1466.115.121.1.44

printable string

 

 

Matching Rules


      是用来指定某属性的匹配规则,实际上就是定义一个特殊的Syntax的别名,让LDAP服务器可以识别,并对定义的属性进行匹配。

 

 

Commonly Used Matching Rules

Name

Type

Description

booleanMatch

equality

boolean

octetStringMatch

equality

octet string

objectIdentiferMatch

equality

OID

distinguishedNameMatch

equality

DN

uniqueMemberMatch

equality

Name with optional UID

numericStringMatch

equality

numerical

numericStringOrderingMatch

ordering

numerical

numericStringSubstringsMatch

substrings

numerical

caseIgnoreMatch

equality

case insensitive, space insensitive

caseIgnoreOrderingMatch

ordering

case insensitive, space insensitive

caseIgnoreSubstringsMatch

substrings

case insensitive, space insensitive

caseExactMatch

equality

case sensitive, space insensitive

caseExactOrderingMatch

ordering

case sensitive, space insensitive

caseExactSubstringsMatch

substrings

case sensitive, space insensitive

caseIgnoreIA5Match

equality

case insensitive, space insensitive

caseIgnoreIA5OrderingMatch

ordering

case insensitive, space insensitive

caseIgnoreIA5SubstringsMatch

substrings

case insensitive, space insensitive

caseExactIA5Match

equality

case sensitive, space insensitive

caseExactIA5OrderingMatch

ordering

case sensitive, space insensitive

caseExactIA5SubstringsMatch

substrings

case sensitive, space insensitive

 

      LDAP的schema的主要元素就是这些了,下面列举出了一些LDAP规定好的或是现在比较通用的schema,一般的LDAP服务器都应该可以识别这些定义。
      这就是一个名为subschema的objectclass的定义:

 

objectclass=(2.5.20.1 NAME 'subschema'  AUXILIARY
 MAY ( dITStructureRules $ nameForms $ ditContentRules $
objectClasses $ attributeTypes $ matchingRules $ matchingRuleUse ) )
 

      首先是ID,这里是2.5.20.1,接着是NAME,AUXILIARY说明是辅助型,之后是可选属性的定义,subschema中没有定义必须属性,如果需要定义,应该和MAY一样,将属性放在MUST()中并用$隔开
      再来看一个属性定义:

 

attributetype ( 2.5.4.3 NAME 'cn' SUP name EQUALITY caseIgnoreMatch )
 

      可以看到cn属性的父属性是name,它相等性匹配于caseIgnoreMatch(匹配原则为EQUALITY,还有如SUBSTR是字符串匹配,ORDERING是顺序匹配)
      syntax定义一般都比较简单,如:

 

( 1.3.6.1.4.1.1466.115.121.1.6  DESC  'String' )
 

      这个定义说明,这一串数字1.3.6.1.4.1.1466.115.121.1.5就代表了LDAP中的字符串,这个数字串的定义和X.500相关,包括了它的存储方式,所占空间大小等。
      最后看看Matching Rule的例子,前面提到了caseIgnoreMatch,就看他的吧

 

attributetype ( 2.5.13.2 NAME 'caseIgnoreMatch'
      SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
 

      其实1.3.6.1.4.1.1466.115.121.1.15 就是LDAP数据类型Directory String的ID,说明前面的cn需要等于这个数据类型才有效。
      还有很多常用schema的定义都在了RFC2252中,LDAP服务器都应该支持这些基本的schema。好了,现在基本对LDAP中的schema有个一个大致的说明,可能有不到位或不妥之处,还望大家指正。

 

 

你可能感兴趣的:(LDAP)