此篇文章花费了好几个晚上,大部分是软件翻译的英文文档,加上自己的理解所写,希望学习者能尊重每个人的努力.

  我有句话想送给每个看我文章的人:

    慢就是快,快就是慢!!!

  另外更希望更多人能从认真从原理学习,分享更多有质量的文章,而不是仅仅转载别人的文章.

  以下仅介绍了OpenLDAP的基本原理和基本配置,至于更高级的配置,还需自行学习,因为有了以下基础,再去建楼,就会

  更加容易,网上有太多文章都太老旧,实在难以让初学者对OpenLDAP有一个全面的基础认识,总搞的人云里雾里,这篇文章

  希望对想学习OpenLDAP的人,打一个好的基础,从而能深入了解它.基本命令我就不贴出来了,希望想深入学习的人,自行学习

  man手册.

        --------------马帮弟子:zcf

LDAP:
  原理:
  https://www.cnblogs.com/wilburxu/p/9174353.html

LDAP:
    它是用来做统一用户身份认证的.即: 你访问CSDN它说你可以用微信登录,你登录微博,它也支持微信登录等,
  这就是一种目录服务, 当然它们不一定用LDAP来做为他们的目录服务.
  LDAP(Light Directory Access Portocol),它是基于X.500标准的轻量级目录访问协议。
  Linux上实现LDAP的工具是 openladp, 通过配置ldap服务器,将用户信息存储在其中,就可以使用ldap协议,
  访问用户数据库,来实现LDAP用户认证.

基本概念:
  目录树概念
    1. 目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
    2. 条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。
    3. 对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。
    4. 属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。

  名词:
    dn(Distinguished Name): “uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一)
    uid(User Id): 用户ID songtao.xu(一条记录的ID)
    ou(Organization Unit): 组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织)
    dc(Domain Component) :域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)

    cn(Common Name): 公共名称,如“Thomas Johansson”(一条记录的名称)
    sn(Surname): 姓,如“许”
    rdn(Relative dn): 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”

配置openLDAP有两种方式:
  slapd.conf
    修改它,需要重新生成数据库文件, 生成后需要重新赋予权限属主属组ldap.ldap .
    接着重新加载slapd 进程, 配置才会生效.若使用单机版,不推荐。
  cn=config:
    修改后,立即生效, 它属于热部署.

    从16年开始OpenLDAP官方都不推荐使用slapd.conf来配置LDAP,因为它太繁琐,修改完配置必须重新生成OpenLDAP数据库,

    这就意味着,OpenLDAP服务器必须停机!!

  LDAP初始化
    [root@rnode6 ~]# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG   #用何种方式都需要.
    [root@rnode6 ~]# cp /usr/share/openldap-servers/slapd.ldif /etc/openldap/slapd.conf
    [root@rnode6 ~]# chown -R ldap.ldap /etc/openldap/
    [root@rnode6 ~]# chown -R ldap.ldap /var/lib/ldap/

    /etc/openldap/
      check_password.conf :   用于密码生成
      ldap.conf:         可支持匿名方式访问LDAP
      slapd.d :     此目录就是cn=config方式管理LDAP所需的目录.
      slapd.ldif :     若需要使用slapd.conf管理LDAP,则需要将此ldif复制到这里,改名为slapd.conf

    /etc/openldap/slapd.d/cn=config/
      olcDatabase={2}hdb.ldif    #CentOS6是bdb CentOS7是 hdb

  编译安装:
    1. yum install openssl-devel gcc libtool-ltdl-devel libtool-ltdl -y

    2. 先编译安装Berkeley DB 5.3.28
      Berkeley DBv6.0.20后不在被openldap支持, 因为Berkeley现在是Oracle公司的.
      cd   berkeley的安装目录/build_unix/      #必须要先进到此目录下,否则编译时会总报错
      ../src/dbinc/configure --prefix=/usr/local/berkeley-db-5.3.28
      make
      make install

    3. 编译openldap
      cd openldap源码目录/
      ./configure --enable-wrappers \      #启用TCP-Wrapper
      CPPFLAGS="-I/usr/local/berkeley-db-5.3.28/include" \
      LDFLAGS="-L/usr/local/berkeley-db-5.3.28/lib -Wl,-rpath,/usr/local/berkeley-db-5.3.28/lib" \
      --prefix=/usr/local/openldap2.4.44

      make
      make install

    LDAP的目录信息:

      LDAP学习小结【仅原理和基础篇】-LMLPHP
  它通常就如上图这样组织, 它是倒树结构, 树根一般是 国家(如:c=CN) 或 域名(dc=zcf,dc=com),
  其次一般定义一个或多个组织(Organization, 简称 o) 或 组织单元(Organization Unit, ou)
  一个组织单元中可包含: 员工, 设备信息(PC/打印机等)相关信息.
  Entry(条目):
    uid=tom,ou=People,dc=example,dc=com      #这称为一个DN, 也叫一个entry(条目)

    LDAP学习小结【仅原理和基础篇】-LMLPHP

  目前比较知名的目录服务产品:
    SUN: SUNONE Directory Server, 特点: 基于文本数据的存储,速度块.
    IBM: IBM Directory Server: 基于DB2数据库存储, 速度一般.
    Oracle: Oracle Internet Directory: 基于Oracle的数据库, 速度一般.
    Mircrosoft:AD :基于Windows系统用户, 数据管理/权限不灵活.
    OpenLDAP: 开源项目,速度快,应用广泛.

   Schema:
    它是基本数据模式, LDIF语法, LDAP管理,是目录中存储数据的规则的集合, 它是一种规范, 或一种数据存储标准.
  Schema根据自己内部规范,保证整个目录树的完整性, 无非法数据, 当你需要在LDAP中添加一些自定义的属性时,
  你就需要自定义Schema了, 若使用默认Schema你就 无法添加这些自己所独有的属性, 因为,若没有Schema这些规范,
  随便添加属性, 整个目录树将变的毫无章法,无法管理!
    Schema是一个标准,定义了OpenLDAP目录树读写和属性存取方式,这也是OpenLDAP能够存储什么数据类型,
  数据有何属性等 均是根据Schema来定义的. OpenLDAP默认的schema文件一般在安装在/etc/openldap/schema/下,
  此目录下每个文件定义了不同的对象和不同的属性. 若想使用schema只需要在配置文件中通过include包含即可.
    grep '*.schema' /etc/openldap/slapd.conf

    /etc/openldap/schema/
    core.schema:     OpenLDAP的核心schema.【它是必须加载的】
    inetorgperson.schema : 它仅次于core, 我们添加账号时,很多要使用到它里面定义的objectClass.
    dyngroup.schema : 这是定义组时使用的schema,包括要使用sudo.schema时,也需要它。
    ppolicy.schema:     若需要做密码策略时,需要导入此schema.
    nis.schema: 网络信息服务(FYI),也是一种集中账号管理实现.
    java.schema: 若需要使用Java程序来操作openLDAP时,需要使用它,让OpenLDAP支持Java.
    cosine.schema : Cosine 和 Internet X.500 (比较有用, 不太懂.)
    misc.schema : Assorted (experimental)
    openldap.schema : OpenLDAP Project(experimental)
    sudo.schema: 定义sudo规则

    在OpenLDAP目录树中,Schema用来指定一个目录中所包含的对象(Objects)的类型(ObjectClass),
  以及每一个对象类型(ObjectClass)中必须提供的属性(Atrribute)和可选属性及对应的属性值.
  在LDIF文件中的数据条目, 可理解为一个具体的对象,是通过Schema来规划创建的, 符合Schema
  标准. 因此Schema是一个数据模型, 用来决定数据按什么方式存储, 并定义存储在OpenLDAP目录树中
  不同条目(entry)下的数据之间的关系,schema需要OpenLDAP配置文件(Slapd.conf 或 cn=config)来
  指定. 以保证当前OpenLDAP服务器可在目录树中定义那些对象类型(objectClass).

  ObjectClass:
    在OpenLDAP目录树中, 每个条目必须包含一个ObjectClass属性,,或多个非必要的ObjectClass,及对应的值,
  有且需至少给一个ObjectClass赋一个值!
    每一个值将用作每个条目在目录树中存储信息的标准,如 可包含哪些属性信息, 我们可将ObjectClass属性值
  理解为一种模板,模板定义哪些信息可存取, 哪些信息不可在目录树中存储.
    ObjectClass和Attribute是由Schema文件来规定的, Schema文件规范ObjectClass的构成、Attribute格式
  以及继承关系.

  ObjectClass可分为三类:
    1. 结构型(Structural) : person 和 organizationUnit
      如person: 它可定义一个人的相关属性,如:他的住址,电话,公司,职位等..
    2. 辅助型(Auxiliary) : extensibeObject
      如:以后若想限制登录,就需要通过借助此objectClass来定义.
    3. 抽象型(Abstract): top, 抽象型的ObjectClass不能直接使用.

  Attribute(属性):
    一个ObjectClass节点具有一系列的Attribute, Attribute可理解为Linux系统当中的变量, 那么变量都有
  相应的值, 那么Attribute也是由相关的值,这些属性的对应值表示每个对象的特点, 但有些条目当中的属性
  是必须指定的(如: 有MUST标记的), 有些是非必要的(如: 由MAY标记的).
  在目录树中常用的Attribute有:
    uid, sn, giveName, I, ObjectClass, dc, ou, cn, mail, telephoneNumber, c 等.
  注意:
    uid: 这里的UID不是Linux系统上的UID,这里的UID是用户登录LDAP的账号.
    sn: 只能写姓.
    giveName: 只能写名字

  ObjectClass示例:
    objectClass: ( 2.5.6.6 NAME 'person'
    SUP top STRUCTURAL
    MUST (sn $ cn)
    MAY (userPassword $ telephoneNumber $ seeAlso $ description))

  说明:
    2.5.6.6 : 这称为Object ID
    若要定义 person 属性, 顶级必须为 top, 因为其属性类型为STRUCTURAL, 必须定义 sn 和 cn 属性.
  MAY定义的userPassword, telephoneNumber, seeAlse, description等4个属性是可有可无的.
  若要定义邮件地址, 国家等属性, 是不可以定义的, 除非你自己定义了相关的
    ObjectClass条目.
      对于此person类型的ObjectClass,后期你要调用,就必须提供sn 和 cn, 查询也一样, 否则Schema检查
    将保错.

  ObjectClass案例2:
    objectClass: (2.5.6.0 NAME 'top'
    ABSTRACT
    MUST (objectClass) )

    objectClass: ( 2.5.6.6 NAME 'person'
    SUP top STRUCTURAL
    MUST (sn $ cn)
    MAY (userPassword $ telephoneNumber $ seeAlso $ description))

    说明:
    此案例,若要定义 top 属性, 必须定义一个objectClass属性. 且此案例中还定义了person属性, 所以要必须定义
    sn 和 cn属性, 以及可附加的属性( userPassword, telephoneNumber, seeAlse, description), 所以此案例中
    必须要定义 3 必要个属性, 即objectClass, sn, cn .
    此案例的下一级 objectClass 可以继承上一级的 objectClass 的属性信息.
    注:
      ObjectClass类型定义的不同,则其属性的相关值信息也是不同的.

    Openldap配置:
      Slapd.conf方式配置Openldap的步骤:
      》slaptest :测试对slapd.conf的配置文件.
      》service slapd restart

    olcLogLevel: <日志级别>

LDIF格式:
    LDIF(LDAP Data Interchanged Format)的轻量级目录交换格式.
    它是存储LDAP配置信息及目录内容的标准文本文件格式, 之所以使用文本文件来存储这些信息,是为了方便
  读取和修改,这也是其它大多数服务配置文件所采用的格式.
    LDIF通常用来交换数据并在OpenLDAP服务器之间互相交换数据, 并且可通过LDIF实现数据文件的导入,
  导出及数据文件的增加, 修改, 重命名等一些操作, 这些信息需要按照LDAP中schema的规范进行操作, 并
  会接受schema的检查, 若不符合OpenLDAP Schema规范要求, 则会提示相关语法错误信息.

LDIF文件格式:
  LDIF 文件每行的结尾是不允许有空格或者制表符存在.
  LDIF 文件允许相关属性可被重复赋值并使用.
  LDIF 文件以 # 号行为注释行.
  LDIF 文件所有赋值方式为: 属性:[空格]属性值.
  LDIF 文件通过空行来区分两条条目.

    注意: 若需要手动定义LDIF文件,添加相关条目,需要了解以上相关特点.
  在OpenLDAP服务器中定义LDIF文件,每个条目中必须包含一个ObjectClass属性, 并赋值!!
  ObjectClass属性有顶级之分, 定义时要了解ObjectClass的相关依赖类型, 否则在添加或
  修改时,也一样会语法报错!!

LDIF文件语法:
  基本语法:
  dn: <distinguished name> #首先要指定要修改那个DN(条目)
  <attrdesc>: <attrvalue> #最常用的attrdesc是changetype: 其值最常用的是 modify
  <attrdesc>: <attrvalue>
  <attrdesc>:: <base64-encoded-value>
  <attrdesc>:< <URL>
  ...

  #: 井号开头行为注释.

  1. 可用空格或制表符开始一个新行
    dn: cn=Barbara J Jensen,dc=exam
    ple,dc=com        #注意: example是分行写了,一定要注意写法,不要在它中间加任何非空字符!!

  2. 多个属性值在单独的行中指定
    cn: Barbara J Jensen
    cn: Babs Jensen

  3.以冒号+空格开头的表示,这是一个Base64编码的字符串.
    cn:: IGJlZ2lucyB3aXRoIGEgc3BhY2U=

  4.从文件中获取属性值,当然它还支持ftp,http等.
    cn:< file:///tmp/value

  下面是三个LDAP条目,每个条目要用空行分割
    dn: cn=Barbara J Jensen,dc=example,dc=com
    cn: Barbara J Jensen
    cn: Babs Jensen
    objectclass: person
    description:< file:///tmp/babs
    sn: Jensen

    dn: cn=Bjorn J Jensen,dc=example,dc=com
    cn: Bjorn J Jensen
    cn: Bjorn Jensen
    objectclass: person
    sn: Jensen

    dn: cn=Jennifer J Jensen,dc=example,dc=com
    cn: Jennifer J Jensen
    cn: Jennifer Jensen
    objectclass: person
    sn: Jensen
    jpegPhoto:: /9j/4AAQSkZJRgABAAAAAQABAAD/2wBDABALD
      A4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQ
      ERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVG
    ...

  5.修改记录格式
    dn: <DistinguishedName>
    changetype: <[modify|add|delete|modrdn]>
    add |delete |replace: <attributetype>

    dn: DN
    changetype: add
    <attrdesc1>: <value1>
    <attrdesc1>: <value2>
    ...
    <attrdescN>: <value1>
    <attrdescN>: <value2>
    ...
    -    #注意: 他是Entry之间的分隔符!!!
    示例:
      dn: cn=Babs Jensen,dc=example,dc=com
      changetype: add
      objectclass: person
      objectclass: extensibleObject
      cn: babs
      cn: babs jensen
      sn: jensen

      dn: DN
      changetype: modify
      add: <attributetype>
      <attrdesc>: <value1>
      <attrdesc>: <value2>
      ...
      -
      replace: <attributetype>    #在进行替换操作时,若要替换的DN不存在,它会提示你添加.
      <attrdesc>: <value1>
      <attrdesc>: <value2>
      ...
      -
      delete: <attributetype> #若不提供<attributeType>则删除整个dn属性集.
      <attrdesc>: <value1>
      <attrdesc>: <value2>
      ...
      -
  示例:
    dn: cn=Barbara J Jensen,ou=People,dc=example,dc=com
    changetype: delete

  以上add,replace,delete综合示例:
    dn: cn=Babs Jensen,dc=example,dc=com
    changetype: modify
    add: givenName
    givenName: Barbara
    givenName: babs
       -
    replace: description
    description: the fabulous babs
    -
    delete: sn
    sn: jensen
    -

    dn: DN
    changetype: [modrdn | moddn]
    newrdn: <newrdn>
    deleteoldrdn: 0 | 1      #1:从条目中删除旧的rdn,0:保留,但修该为非区分属性.
    newsuperior: <DN>    #若存在,则将条目移动到新上级.
    ...
    -
  示例:
    dn: cn=Babs Jensen,dc=example,dc=com
    changetype: modrdn
    newrdn: cn=Barbara J Jensen
    deleteoldrdn: 0
    newsuperior: ou=People,dc=example,dc=com

    dn: cn=Barbara J Jensen,ou=People,dc=example,dc=com
    changetype: delete #这样写,将删除dn这个准确名属性集.

  6.包含外部LDIF文件.
    dn: dc=example,dc=com
    objectclass: domain
    dc: example

    include: file:///tmp/example.com.ldif

    dn: dc=example,dc=org
    objectclass: domain
    dc: example

  服务端命令和客户端命令:
    slap[passwd|...]      #凡是slap开头的命令都是服务端命令.
    ldap[passwd|add|..]    #客户端命令

  LDIF 示例:
    dn: uid=Green Tom,ou=people,dc=test,dc=com    #DN描述项,在整个目录树上是唯一的.
    objectClass: top
    objectClass: posixAccount
    objectClass: shadowAccount
    ojbectClass: person
    objectClass: inetOrgPerson
    objectClass: hostObject
    sn: Green
    cn: Green Tom
    telephoneNumber: 010 12345678
    mail: [email protected]
    注:
    冒号后面必须有一个空格, 然后才是属性值, schema规范定义要求很严格!!

openLDAP的使用
    openLDAP它可以帮助我们构建自己的企业目录服务, 所谓目录服务,其实就是将一个组织的内部,
  各个部门等,使用一种结构构建出来,方便我们来管理整个公司内的所有事物, 包括员工, PC, 打印机
  等等... 目录服务帮我们构建的组织架构就如下图:
  什么是组织架构?
    抽象图:

      第一张图就是抽象概念,第二张图就是实际工作中会使用的.
    此图是OpenLDAP的倒树架构图
    树根: dc=com 这是顶级域
    dc=example 这是二级域,也就是我们组织机构的根.
    ou=People, ou=Servers 这都是组织内部的组织单元,可理解为部门.
    其中ou=Servers,它是一个特殊ou,一般使用它表示,它下面可以有很多子ou.
    uid=babs 这是一个用户相关的条目

    企业组织架构图:
      这张图中是企业中真正使用的架构图
      dc=zcf,dc=com #这就是zcf.com域
      它下面有很多ou, 每个ou下面是具体的用户.
      注意:
        在创建组织架构时, 用户和组是分开的,就类似于MS AD(活动目录).

  使用yum安装的openldap做基本初始化步骤

    一. 首先配置主机名可被解析
      #因为openLDAP执行命令时,它需要解析主机名, 若不能成功解析,它将一直等到解析超时才会
      #将命令的执行结果返回.
        echo IP HostName >> /etc/hosts

    二. 导入必要的schema:
      cd /etc/openldap/slapd.d/cn=config/cn=schema
      ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/ppolicy.ldif
      ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
      ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
      注:
        additional info: olcObjectClasses: AttributeType not found: "audio"
          若出现这个错误, 就是cosine.ldif还没有导入导致的.
      ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
      注:
        additional info: olcObjectClasses: AttributeType not found: "manager"
        若出现这个错误, 就是cosine.ldif还没有导入导致的.
      ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/dyngroup.ldif

      ls #导入成功后,会有这些文件.

    三. 修改域名, 管理员帐户, 禁止匿名查询
      cat /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
      olcSuffix: dc=my-domain,dc=com
      olcRootDN: cn=Manager,dc=my-domain,dc=com
        #要将这些信息修改为,自己的域名和RootDN, RootDN就是openldap的管理员账号名.

      cat /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif
        olcAccess: ....
        #这里定义了openldap的监控信息, 需要修改为适合自己需要的内容.

      vim moddomain.ldif
        dn: olcDatabase={1}monitor,cn=config
        changetype: modify
        replace: olcAccess
        olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
        al,cn=auth" read by dn.base="cn=Manager,dc=zczf,dc=com" read by * none

        dn: olcDatabase={2}hdb,cn=config
        changetype: modify
        replace: olcSuffix
        olcSuffix: dc=zczf,dc=com

        dn: olcDatabase={2}hdb,cn=config
        changetype: modify
        replace: olcRootDN
        olcRootDN: cn=Manager,dc=zczf,dc=com

        dn: olcDatabase={2}hdb,cn=config
        changetype: modify
        add: olcRootPW
        olcRootPW: {SSHA}GqkPrqlMNqjZVxcRqHPcwqc3usvzYmyd

        dn: cn=config
        changetype: modify
        add: olcDisallows
        olcDisallows: bind_anon
    注: 这里修改了两个文件, 分别是olcDatabase={1}monitor.ldif 和 olcDatabase={2}hdb.ldif
  在monitor文件中修改了 olcAccess: 这个字段, 修改方式是替换(replace), 主要是修改值中的域名, 其它字段不变.
  数据库文件hdb中是修改了olcSuffix 和 olcRootDN, 修改类型也是替换, 主要是修改成自己的域名.
  由于数据库hdb中没有root密码字段, 所以要先添加 olcRootPW, 再赋值为新密码.
  最后一个 olcDisallows 是定义禁止登录, 这里是设置匿名用户不能登录LDAP.

  执行修改:
    ldapadd -Y EXTERNAL -H ldapi:/// -f moddomain.ldif

    四. 创建自己的组织架构
      下面将创建的组织架构图:

        LDAP学习小结【仅原理和基础篇】-LMLPHP

    1. 创建先创建顶级域 和 两个ou(people, group)组织架构:

    vim newZCFcom.ldif
      dn: dc=zcf,dc=com
      objectClass: dcObject
      objectClass: organization
      dc: zcf
      o: zcf.com
      注: 这里先定义了一个顶级域zcf.com
    并配置了两个objectClass, 这两个对象要引用,必须提供dc 和 o 这两个属性.
    因为包含它们的schema定义文件中是这么定义的,你要引用该ObjectClass,
    就必须遵守这些规则. 我看到objectClass通常写一块,而这些对象所必须的属性
    写一块, 所以,具体dc和o是被他俩谁要求,必须提供的,我还不清楚.

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

      dn: ou=Group,dc=zcf,dc=com
      objectClass: organizationalUnit
      ou: Group

      dn: cn=Manager,dc=zcf,dc=com    #Manger: 是默认管理员的cn名,建议修改.
      objectClass: organizationalRole
      cn: Manager           #cn: 公共名, 需要注意:冒号前有空格, 结尾不能有空格
    这里定义管理员的RootDN.即管理员帐户

      dn: cn=appteam,ou=Group,dc=zcf,dc=com
      objectClass: posixGroup
      cn: Host
      gidNumber: 1010
      #这里引用了一个posixGroup的对象, 它需要提供cn 和 gidNumber.

      dn: cn=dbateam,ou=Group,dc=zcf,dc=com
      objectClass: posixGroup
      cn: Host
      gidNumber: 1011

      dn: cn=host,ou=Group,dc=zcf,dc=com
      objectClass: posixGroup
      cn: Host
      gidNumber: 1012
      #多加一个组,图中没画出来, 它用来存放所有PC的信息.

  2. 执行添加:
    ldapadd -x -D cn=Manager,dc=zcf,dc=com -W -f newZCFcom.ldif
    #-x: 使用SASL做简单认证. -W: 提示输入密码 -D: 指明LDAP的管理员账号名,即rootdn

  3. 接下来对刚创建的组织架构做查询 并 验证:
    建议每次配置完成后,都要做验证!
    查询可通过GUI工具 或 命令.
    1. 命令方式:
      vim /etc/openldap/ldap.conf
        BASE   dc=zcf,dc=com
        URI     ldap://      #当前主机OpenLDAPServer的IP或主机名

      ldapsearch -x -LLL        #这样就可以直接获取刚添加的条目信息了

    2. GUI工具
      ldapadmin    #这是一个windows上的绿色小工具,它虽小,但功能却非常强大!

    4. 创建要添加的用户:
      cat addUser.ldif
        dn: uid=zhangchaofeng,ou=People,dc=zcf,dc=com
        objectClass: inetOrgPerson
        objectClass: posixAccount
        objectClass: shadowAccount
        homeDirectory: /home/zhangchaofeng
        userPassword: {SSHA}78DMFNXKLvUl+tjCi2haD+U0DASQ/MJK
        loginShell: /bin/bash
        cn: zhangchaofeng
        uidNumber: 2000
        gidNumber: 1010
        sn: System Administrator
        mail: [email protected]
        postalAddress: Beijing
        mobile: 12345678900

        dn: uid=ldap01,ou=People,dc=zczf,dc=com
        objectClass: inetOrgPerson
        objectClass: posixAccount
        objectClass: shadowAccount
        homeDirectory: /home/ldap01
        userPassword: {SSHA}78DMFNXKLvUl+tjCi2haD+U0DASQ/MJK
        loginShell: /bin/bash
        cn: ldap01
        uidNumber: 2001
        gidNumber: 1011
        sn: dba
        mail: [email protected]
        postalAddress: Beijing
        mobile: 12345678901

    注: 以上添加了两个条目(entry), 条目和条目之间要用空行隔开!!

    5. 执行添加:
      ldapadd -x -D 'cn=Manager,dc=zcf,dc=com' -W -f addUser.ldif

    6. 验证是否添加成功
      ldapsearch -x -D 'cn=Manager,dc=zcf,dc=com' -W -LLL 'uid=ldap01'
        #具体语法参见下文
        # -x: 使用SASL做简单认证, SASL是将用户名和密码直接加到URL中传输,
          只是它会预先使用共享密钥对密码做加密.
        #-D 和 -W 要配合使用, -D指明以什么身份登录查询,默认是匿名身份,但前面
          通过cn=config方式关闭了匿名,所以必须指明身份, -W:提示输入密码.
        #-LLL: 这是查询级别, 分三级, -L, -LL, -LLL

 五. 配置TLS方式对外提供目录服务
    测试环境为RHEL7.4, 客户端为CentOS7.6 , 客户端在连接服务端认证时,若不是安全连接,
  将导致客户端能够获取 ldap用户的帐户信息, 但无法获取密码,导致登录失败!!

  OpenLDAP 向cn=config中添加TLS证书认证的方式:
    A. 创建CA:
      1. 创建的CA的私钥
        openssl genrsa -out cakey.pem 2048
      2. 创建CA的自签发证书
        openssl req -new -x509 -key cakey.pem -out cacert.pem \
          -subj /C=CN/ST=Beijing/L=Changping/O=zczf/CN=ca.zczf.com
      3. 创建CA签发证书的工作目录:
        mkdir certs newcerts crl private
        echo 01 > serial ---->创建证书生成列表的序列号文件
        echo 01 > crlnumber ---->创建证书吊销列表的序列号文件;【注意:若不需要吊销证书也可不创建】
        mv cakey.pem private/
        cp /etc/pki/tls/openssl.cnf .
        vim openssl.cnf
          dir = 当前目录的绝对路径.

   B. 签发证书:
      4. 创建LDAPServer的私钥
        openssl genrsa -out ldap.key 2048
      5. 创建LDAPServer向CA申请签发证书的请求
        openssl req -new -key ldap.key -out ldap.csr \
          -subj /C=CN/ST=Beijing/L=Changping/O=zczf/CN=ldap.zczf.com
      6. 使用CA的私钥签发此证书申请
        openssl ca -in ldap.csr -out ldap.crt -days 365 -config openssl.cnf

  C. 配置LDAP支持证书:
    1.将生成的证书复制到:
      cp ldap.key ldap.crt cacert.pem /etc/openldap/cacerts/

    2. 编写下面的LDIF文件:
      以下内容主要是在/etc/openldap/slapd.d/cn=config.ldif 文件添加系统配置.
      以下添加的了 OpenLDAP Server将启用TLS功能, 告诉OpenLDAP Server
      olcTLSCACertificatePath: CA的证书目录在哪里.
      olcTLSCACertificateFile: CA的证书文件叫什么, 这里建议写绝对路径.
      olcTLSCertificateFile: 指明OpenLDAP Server的证书在哪里.
      olcTLSCertificateKeyFile: 指明OpenLDAP Server的Key在哪里
      olcTLSVerifyClient: never: 表示从来不对客户端做证书验证.
    vim updateldapTLS.ldif
      dn: cn=config
      changetype: modify
      replace: olcTLSCACertificatePath
      olcTLSCACertificatePath: /etc/openldap/cacerts
      -
      add: olcTLSCACertificateFile
      olcTLSCACertificateFile: /etc/openldap/cacerts/cacert.pem
      -
      replace: olcTLSCertificateFile
      olcTLSCertificateFile: /etc/openldap/cacerts/ldap.crt
      -
      replace: olcTLSCertificateKeyFile
      olcTLSCertificateKeyFile: /etc/openldap/cacerts/ldap.key
      -
      add: olcTLSVerifyClient
      olcTLSVerifyClient: never

   3.执行添加, 将自动将上面的条目添加/etc/openldap/slapd.d/cn=config.ldif
      ldapmodify -Y EXTERNAL -H ldapi:/// -f updateldapTLS.ldif
      注: -Y EXTERNAL :这个我还不清楚是什么意思.

     4. 修改slapd.service脚本的启动参数文件
      vim /etc/sysconfig/slapd
        #若用不到非加密的方式,也可以去掉 ldap:/// (389)
        #添加ldaps:/// 后,slapd就会监听默认TLS端口636.
        # ldapi:// : 这个是Socket方式连接.
        SLAPD_URLS="ldapi:/// ldaps:/// ldap:///"

    5. 重启slapd服务
      systemctl restart slapd

   6. TLS证书添加完成后,还需要在服务器端配置本地openldap 客户端与slapd交互使用的TLS证书.
      cat   /etc/openldap/ldap.conf
        BASE dc=zcf,dc=com
        URIldaps://ldap.zczf.com
        TLS_CACERT /etc/openldap/cacerts/cacert.pem
        TLS_CACERTDIR/etc/openldap/cacerts
        TLS_REQCERT allow
        注:
          URI: 要使用ldaps://
          TLS_CACERT: 指名CA的证书在哪里.
          TSL_CACERTDIR: 指明CA证书所在目录
          TLS_REQCERT:
          allow: 若服务器端证书验证失败,也依然允许连接.
      此配置文件修改好后:
        ldapsearch -D 'cn=admin,dc=zcf,dc=com' -W -LLL
        #输入密码后, 命令能执行成, 则说明ldaps已经配置成功。

  以上所有配置就完成了LDAP Server端的配置.

       D. 接下来就需要配置客户端访问了:
      1. 安装客户端支持包
        yum install openldap-clients nss-pam-ldapd authconfig

      2. 在做以下配置前, 先做备份
        因为openldap认证配置要修改很多系统文件, 为了避免配置错误,而导致手工查找这些
        配置文件,去删除,所以建议一定要备份!!
        它大概会修改以下文件:
          CentOS7.6和之前的版本修改的文件多少是不同!!!
        相同的文件:
          /etc/nslcd.conf
          /etc/openldap/ldap.conf
          /etc/pam.d/system-auth-ac
          /etc/nsswitch.conf
        不同的文件:
          /etc/pam.d/password-auth-ac
        还有些其他文件, 我没完全测试到.

        authconfig --savebackup=openldapconf.bak
          #若需要恢复:
            authconfig --restorebakcup=openldapconf.bak
            或
            authconfig --restorelastbakcup
            #这是在第一次操作时忘记备份了,可用它来恢复到
              最进一次操作前的状态, 因为是第一次操作,最近
              一次就是系统安装好时的状态!!

       3. 接下来就可以配置客户端使用LDAP认证了.
      authconfig --enableldap --enableldapauth \
        --ldapserver=ldaps://ldap.zcf.com \
        --ldapbasedn="dc=zcf,dc=com" \
        --enableldaptls \
        --ldaploadcacert=http://ldap.zczf.com/cacert.pem \
        --enablemkhomedir \       #RHCE考试题,中不要加此选项!!
        --update
      注:
        启用LDAP, 启用LDAP认证,是必须要有的.
      虽然后面指明了要使用TLS,但ldapserver的地址依然不能直接写,
      必须要加上ldaps:// 这个协议头部, 另外CA证书必须提供URL地址,
      让authconfig自己下载; enablemkhomedir: 若你需要使用autofs,
      来自动管理用户家目录的创建,挂载,就不能使用此选项.
      另注:
        authconfig-gtk          #这是authconfig的图像工具, 也可使用它来配置LDAP.

    4. 在客户端验证是否学习到LDAP服务器上的用户信息:
      id ldapuser01
      getent passwd ldapuser01
      getent shadow ldapuser01 #这个好像不能在返回用户密码了.
        另外: CentOS7.6上配置LDAP客户端时,若不支持TLS或SSL,
          将不允许LDAP用户登录系统.

    5. 验证登录
      ssh ldapuser01@IP

  六. 配置允许用户修改自己的密码
    vim allowModPasswd.ldif
      dn: olcDatabase={2}hdb,cn=config
      changetype: modify
      add: olcAccess
      olcAccess: {0}to attrs=userPassword,shadowLastChange by
      dn="cn=admin,dc=zczf,dc=com" write by anonymous auth by self write by * none
      olcAccess: {1}to dn.base="" by * read
      olcAccess: {2}to * by dn="cn=admin,dc=zczf,dc=com" write by * read

    ldapmodify -Y EXTERNAL -H ldapi:/// -f allowModPasswd.ldif

    验证用户是否可以修改自己的密码.

  七. 配置ldap用户在登录时, 使用autofs来自动挂载家目录

   NFS Server:
      1. mkdir -pv /ldaphome/ldap0{1,2,3}
      2. chmod o+w -R /ldaphome/

      3, yum install nfs-utils
      4, vim /etc/exports
        /ldaphome/ldapadmin192.168.10.0/24(rw,sync)
        /ldaphome/ldap01 192.168.10.0/24(rw,sync)
        /ldaphome/ldap02 192.168.10.0/24(rw,sync)

      5. systemctl restart nfs
      6. showmount -e localhost

  

  Client:
    1. yum install autofs sssd
      注:
      sssd: (System Security Services Dameon)
        https://blog.csdn.net/liu16659/article/details/80997333

    2. vim /etc/auto.master
      /home/ldap      /etc/auto.misc

      3.mkdir  /home/ldap       #这个目录必须存在!!!

      4.vim /etc/auto.misc
      *       -rw,vers=3,soft,intr      nfs.server.com:/userhome/&

        注: &可匹配到的ldap用户名,* 是前向引用.引用匹配到的用户名.

         -fstype=nfs,soft,intr,vers,sync都非必须,但rw是必须的!!

     5. 配置LDAP认证

    authconfig --savebackup=ldap.bak
    authconfig --enableldap --enableldapauth  \

      --ldapserver=ldap://server.group8.example.com  --ldapbasedn="dc=group8,dc=example,dc=com" \

        --enableldaptls  --ldaploadcacert=http://172.25.0.254/pub/cacert.pem --update

   6. 测试su登录

      若能正常挂载NFS共享,并看到其中的文件,则说明成功.

  

    7.若出现autofs挂载失败的情况,可参考:【坑好多,请注意!!!】

        1. nfs导出配置是否正确, IP, 权限.
      2. autofs中auto.master中填写的目录,必须存在.
      3. auto.misc中的配置一定要有rw。
      4. 系统时间是否同步

    原因不明:
      autofs 服务启动时报了一个错误:
      automount[20951]: setautomntent: lookup(sss): setautomntent: No such file or directory
        但网上查询,没有找到答案, 我在另一台别人配置好的VM中,查看,他的autofs也报这个错误,但ldap
        用户却可以正确自动挂载nfs共享的家目录. 不清楚原因.但最近做成功后,没有这个错误了!!

    以上配置完成后, openLDAP的基本使用已经完成!

OpenLDAP修改管理员密码
  1. 直接回车输入密码,它会生成密码字符串.
    slappasswd
    注:
      echo 123456 |xargs slappasswd -s
        #-s: 指定要生成的明文密码

  2. 创建一个ldif 文件,来修改管理员密码
    vim modrootpw.ldif
      dn: olcDatabase={0}config,cn=config
      changetype: modify
      add: olcRootPW
      olcRootPW: {SSHA}xxxx

   3. 执行修改命令
    ldapadd -Y EXTERNAL -H ldapi:/// -f modrootpw.ldif
    或
      ldapmodify -a -Y EXTERNAL -H ldapi:/// -f modrootpw.ldif
        #-a: 其实就是 ldapadd, 因为ldapadd是ldapmodify的硬链接
      注:
      [root@rnode6 ~]# cat /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif
        # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
        # CRC32 ba5c9427
        dn: olcDatabase={0}config
        objectClass: olcDatabaseConfig
        olcDatabase: {0}config
        olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
        al,cn=auth" manage by * none
        structuralObjectClass: olcDatabaseConfig
        entryUUID: ec40f8c2-e643-1038-8c1d-e1c3847c1ae1
        .......
        查看openldap的olcDatabase={0}config.ldif 这个配置文件,发现其中没有olcRootPW字段,所以
        要修改管理员密码,需要先添加该字段才可以.
        如:
          上面示例中:
          dn: olcDatabase={0}config,cn=config
            #这段是告诉,openLDAP,要操作的dn是 olcDatabase={0}config这个配置文件,
               它的上级目录是cn=config
          changetype: modify         # 这是告诉openLDAP,我要做修改操作.
          add: olcRootPW          # 这是告诉openLDAP,我要添加一个字段叫 olcRootPW
          olcRootPW: {SSHA}xx      # 这是给olcRootPW 字段 赋值,要注意: 属性必须要有值!!
            另外: 属性名: 后必须要有一个空格!!

      当执行完成后, cat /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif
      就会发现修改了,而且时间戳也修改了.

ldap日志:
  查看日志级别:
    slapd -d ?
    或
      查看官网的说明.

    debug level:
      -1: 安装调试时,开启,输出所有信息.
      0: 关闭debug
      1: 跟踪函数调用
      2:跟踪一个包

   启用 OpenLDAP 的日志功能:
    1. 默认openLDAP使用的rsyslog来处理自己的日志, 它会将日志发送给 local4 这个设备, 来接受.
      vim /etc/rsyslog.conf
        local4.* /var/log/ldap.log

    2. 使用cn=config方式来管理启用日志
    默认openLDAP是不开启日志的, 需要需要首先添加在olcLoglevel对象,并给它赋值.
      cat << EOF | ldapmodify -Y EXTERNAL -H ldapi:///
        dn: cn=config
        changetype: modify
        add: olcLoglevel
        olcLoglevel: -1
      EOF

  3. 重启rsyslog 和 slapd即可.

    注: 若是使用的是slapd.conf 则可使用以下方式来开启.

    此方式仅做参考,它是slapd.conf配置openLDAP的方式,现在已不建议使用:
      vim slapd.conf
        loglevel [-1 | any]
      

      slaptest -f  /etc/openldap/slapd.conf      #测试配置文件是否有语法错误.
      rm -rf /etc/openldap/slapd.d/*
          #重新生成slapd.d这些系统数据库配置文件.
      slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d/
      chown -R ldap.ldap /etc/openldap

      #最后还是重启 rsyslog 和 slapd

05-10 19:04