跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Linux Enterprise Desktop 文档 / 安全和强化指南 / 身份验证 / 使用 389 Directory Server 的 LDAP
适用范围 SUSE Linux Enterprise Desktop 15 SP6

5 使用 389 Directory Server 的 LDAP

轻量级目录访问协议 (LDAP) 是用来访问和维护信息目录的协议。LDAP 可用于执行多种任务,例如用户和组管理、系统配置管理和地址管理。在 SUSE Linux Enterprise Desktop 15 SP6 中,LDAP 服务由取代了 OpenLDAP 的 389 Directory Server 提供。

理想情况下,中心服务器会将数据储存在一个目录中,并使用明确定义的协议将其分发到所有客户端。结构化数据使各种应用程序都能对其进行访问。中心储存库减少了必要的管理工作。利用 LDAP 这样的标准化开放协议可以确保尽可能多的客户端应用程序都能访问这些信息。

这里所说的目录实际上是指一种经过优化能够快速有效地读取和搜索的数据库。存储在此目录中的数据类型往往会长期保留,且不会经常更改。这样,便可以针对高性能的并发读取优化 LDAP 服务,而传统数据库的优化目的是在短时间内接受大量的数据写入。

5.1 LDAP 目录树的结构

本节介绍 LDAP 目录树的布局,并提供 LDAP 相关的基本术语。

LDAP 目录具有树形结构。目录中的所有项(称为对象)在此层次结构中都有确定的位置。此层次结构称为目录信息树 (DIT)。所需项的完整路径(可以明确标识该项)称为判别名 (DN)。树中的对象由其相对判别名 (RDN) 标识。判别名是基于项路径中的所有项的 RDN 构建的。

LDAP 目录树中的关系在下例中尤为明显,如图 5.1 “LDAP 目录的结构”所示。

LDAP 目录的结构
图 5.1︰ LDAP 目录的结构

完整的图是一个虚构的目录信息树。其中描述了三个层次上的项。每个项对应于图中的一个框。在本例中,虚构员工 Geeko Linux 的完整有效判别名cn=Geeko Linux,ou=doc,dc=example,dc=com。该名称是通过将 RDN cn=Geeko Linux 添加到前置项 ou=doc,dc=example,dc=com 的 DN 来构成的。

可存储在 DIT 中的对象类型是按照纲要全局确定的。对象类型由对象类决定。对象类确定必须或可以分配给相关对象的属性。纲要包含 LDAP 服务器可以使用的所有对象类和属性。属性是结构化数据类型。其语法、顺序和其他行为由纲要定义。LDAP 服务器会提供一组可在各种环境中工作的核心纲要。如果您需要使用自定义纲要,可以将其上载到 LDAP 服务器。

表 5.1 “常用对象类和属性”提供了示例中所用 00core.ldif06inetorgperson.ldif 中的对象类的简单概览,包括必需的属性(必需属性)和有效的属性值。安装 389 Directory Server 后,可以在 /usr/share/dirsrv/schema 中找到这些项。

表 5.1︰ 常用对象类和属性

对象类

含义

示例项

必需属性

domain

域的名称组成部分

示例

displayName

organizationalUnit

组织单元

documentationdept

ou

nsPerson

内部网或互联网中与个人相关的数据

Tux Linux

cn

例 5.1 “CN=schema 的摘录”显示了某个纲要指令的摘录及其解释。

例 5.1︰ CN=schema 的摘录
attributetype (1.2.840.113556.1.2.102 NAME 'memberOf' 1
       DESC 'Group that the entry belongs to' 2
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 3
       X-ORIGIN 'Netscape Delegated Administrator') 4

objectclass (2.16.840.1.113730.3.2.333 NAME 'nsPerson' 5
       DESC 'A representation of a person in a directory server' 6
       SUP top STRUCTURAL 7
       MUST ( displayName $ cn ) 8
       MAY ( userPassword $ seeAlso $ description $ legalName $ mail \
             $ preferredLanguage ) 9
       X-ORIGIN '389 Directory Server Project'
  ...

1

属性的名称、其唯一对象标识符(OID,数字格式)和属性的缩写。

2

通过 DESC 对该属性提供的简要说明。在此还可以指出定义所基于的相应 RFC。

3

可保存在该属性中的数据类型。在本例中,它是一个不区分大小写的目录字符串。

4

纲要元素(例如项目的名称)的来源。

5

对象类 nsPerson 的定义以 OID 以及该对象类的名称开头(与属性的定义类似)。

6

对象类的简要说明。

7

SUP top 项指示此对象类不从属于另一个对象类。

8

MUST 列出必须对 nsPerson 类型的对象使用的所有属性类型。

9

MAY 列出可选择对此对象类使用的所有属性类型。

5.2 为 389 Directory Server 创建和管理 Docker 容器

注意
注意

本节为选读内容;如果您使用 389 Directory Server 实例作为 Docker 容器,请参考本节。有关 389 Directory Server 实例的常规用法,请参见其余小节。

要创建 389 Directory Server 实例并将其作为 Docker 容器进行管理,请参见以下示例:

提取最新的 389 Directory Server 映像

要从容器注册表中提取最新的 389 Directory Server 映像,请运行以下命令:

>  docker pull 389ds/dirsrv:latest
创建新卷

要为容器创建新卷,请运行以下示例命令:

>  docker volume create VOLUME
使用基本配置创建容器

要使用基本配置创建容器,请运行以下示例命令:

>  docker create \
 -u USERNAME \
 -e SUFFIX_NAME="dc=example,dc=com" \
 -e DS_DM_PASSWORD=PASSWORD \
 -m 1024M \
 -p 3389:3389 -p 3636:3636 \
 -v VOLUME:/data \
 --name INSTANCE \
 389ds/dirsrv:latest
启动 389 Directory Server 的 Docker 容器

要启动 Docker 容器,请运行以下示例命令:

>  docker start INSTANCE
在正在运行的 389 Directory Server 容器中执行命令

如果容器 (PID 1) 的主进程正在运行,您可以使用以下语法在正在运行的 389 Directory Server 容器中运行命令:

> sudo docker exec -u USERNAME -i -t INSTANCE COMMAND
注意
注意:COMMAND 必须可执行

要运行链式命令或括在引号中的命令,应先在容器中运行外壳会话。例如,您可以在附加到容器的 sh 外壳中运行命令:

> sudo docker exec -u USERNAME -i -t INSTANCE sh -c "COMMAND"
停止 389 Directory Server 的 Docker 容器

要停止正在运行的 Docker 容器,请运行以下示例命令:

>  docker stop INSTANCE
去除 389 Directory Server 的 Docker 容器

要去除 Docker 容器,请运行以下示例命令:

>  docker rm INSTANCE

5.3 安装 389 Directory Server

使用以下命令安装 389 Directory Server:

> sudo zypper install 389-ds

安装后,设置服务器。

5.3.1 设置新的 389 Directory Server 实例

您需要使用 dscreate 命令来创建新的 389 Directory Server 实例,并使用 dsctl 命令彻底去除这些实例。

可以基于自定义配置文件以及基于自动生成的模板文件这两种方式来配置和创建新实例。对于测试实例,您可以使用自动生成的模板,而无需进行任何更改,不过,对于生产系统,则必须仔细检查该模板并进行任何必要的更改。

然后,您需要设置管理身份凭证,管理用户和组,并配置身份服务。

389 Directory Server 由三个主要命令控制:

dsctl

管理本地实例,需要 root 权限。要求您连接到运行目录服务器实例的终端。用于启动、停止和备份数据库以及进行其他操作。

dsconf

用于管理和配置服务器的主要工具。可通过实例的外部接口管理其配置。这样,您便可以在该实例上远程更改配置。

dsidm

用于身份管理(管理用户、组、口令等)。权限由访问控制授予,因此,举例而言,用户可以重置自己的口令或更改自己帐户的细节。

执行以下步骤可设置一个用于测试和开发的简单实例,并在其中填充少量的示例项。

5.3.2 使用自定义配置文件创建 389 Directory Server 实例

您可以基于一个简单的自定义配置文件创建新的 389 Directory Server 实例。此文件必须采用 INF 格式,您可以随意为其命名。

默认实例名称为 localhost。创建实例后,便无法更改实例名称。最好创建自己的实例名称,而不要使用默认名称,这样可避免产生混淆并更加容易理解实例全程是如何工作的。以下示例使用实例名称 LDAP1 和后缀 dc=LDAP1,dc=COM

例 5.2 显示了一个可用于创建新 389 Directory Server 实例的示例配置文件。您可以复制并按原样使用此文件。

  1. 将以下示例文件 LDAP1.inf 复制到您的主目录:

    例 5.2︰ 最小 389 Directory Server 实例的配置文件
    # LDAP1.inf
    
    [general]
    config_version = 2 1
    
    [slapd]
    root_password = PASSWORD2
    self_sign_cert = True 3
    instance_name = LDAP1
    
    [backend-userroot]
    sample_entries = yes 4
    suffix = dc=LDAP1,dc=COM

    1

    此行为必需的指令,指示这是版本 2 的 INF 设置文件。

    2

    为 ldap 用户 cn=Directory Manager 创建强口令 root_password。此用户用于连接(绑定)到目录。

    3

    /etc/dirsrv/slapd-LDAP1 中创建自我签名的服务器证书。

    4

    在新实例中填充示例用户和组项。

  2. 要根据例 5.2 创建 389 Directory Server 实例,请运行以下命令:

    > sudo dscreate -v from-file LDAP1.inf | \
    tee LDAP1-OUTPUT.txt

    这会显示创建实例期间发生的所有活动,将所有消息存储在 LDAP1-OUTPUT.txt 中,并在大约一分钟内创建一个正常工作的 LDAP 服务器。详细输出包含大量有用的信息。如果您不想保存这些信息,请删除该命令的 | tee LDAP1-OUTPUT.txt 部分。

  3. 如果 dscreate 命令失败,将显示消息告诉您原因。更正所有问题后,去除该实例(参见步骤 5)并创建新实例。

  4. 如果安装成功,将报告 Completed installation for LDAP1。检查新服务器的状态:

    > sudo dsctl LDAP1 status
    Instance "LDAP1" is running
  5. 以下命令可用于彻底去除实例。第一条命令执行试运行,而不会去除实例。当您确定要去除时,请结合 --do-it 选项使用第二条命令:

    > sudo dsctl LDAP1 remove
    Not removing: if you are sure, add --do-it
    
    > sudo dsctlLDAP1 remove --do-it

    此命令还会去除未完整安装的或已损坏的实例。您可以放心地按所需的频率创建和去除实例。

如果您忘记了实例的名称,可使用 dsctl 列出所有实例:

> sudo dsctl -l
slapd-LDAP1

5.3.3 基于模板创建 389 Directory Server 实例

可以使用 dscreate 命令为新 389 Directory Server 实例自动创建模板。这会创建一个模板,您可以按原样使用该模板进行测试。对于生产系统,请检查该模板并根据您自己的要求进行更改。默认值在模板文件中都有说明,并已注释掉。要进行更改,请取消注释默认值并输入您自己的值。所有选项都有详细的说明。

下面的示例会将模板输出到 stdout:

> sudo dscreate create-template

这有助于快速检查模板,但是,您必须创建一个文件用于创建新 389 Directory Server 实例。您可以对此文件随意命名:

> sudo dscreate create-template TEMPLATE.txt

下面是新文件中的代码段:

# full_machine_name (str)
# Description: Sets the fully qualified hostname (FQDN) of this system. When
# installing this instance with GSSAPI authentication behind a load balancer, set
# this parameter to the FQDN of the load balancer and, additionally, set
# "strict_host_checking" to "false".
# Default value: ldapserver1.test.net
;full_machine_name = ldapserver1.test.net

# selinux (bool)
# Description: Enables SELinux detection and integration during the installation
# of this instance. If set to "True", dscreate auto-detects whether SELinux is
# enabled. Set this parameter only to "False" in a development environment.
# Default value: True
;selinux = True

它会自动从您的现有环境配置某些选项,例如系统的完全限定域名(在模板中名为 full_machine_name)。按原样使用此文件来创建一个新实例:

> sudo dscreate from-file TEMPLATE.txt

这会创建一个名为 localhost 的新实例,并在创建后自动启动该实例:

> sudo dsctl localhost status
Instance "localhost" is running

使用默认值会创建一个完全可正常运行的实例,不过您也可以更改某些值。

创建实例后,便无法更改实例名称。最好创建自己的实例名称,而不要使用默认名称,这样可避免产生混淆并更加容易理解实例全程是如何工作的。为此,请取消注释 ;instance_name = localhost 行并将 localhost 更改为您选择的名称。在以下示例中,实例名称为 LDAP1

另一项有用的更改是在新实例中填充示例用户和组。取消注释 ;sample_entries = no 并将 no 更改为 yes。这会创建 demo_userdemo_group

通过取消注释 ;root_password 并将默认口令替换为您自己的口令来设置口令。

模板不会创建默认后缀,因此您应在 suffix 行中配置自己的后缀,如下例所示:

suffix = dc=LDAP1,dc=COM

可以使用 dsctl 彻底去除任何实例,然后重新开始创建:

> sudo dsctl LDAP1 remove --do-it

5.3.4 停止和启动 389 Directory Server

以下示例使用 LDAP1 作为实例名称。使用 systemd 管理 389 Directory Server 实例。获取实例的状态:

> systemctl status --no-pager --full dirsrv@LDAP1.service
   ● dirsrv@LDAP1.service - 389 Directory Server LDAP1.
     Loaded: loaded (/usr/lib/systemd/system/dirsrv@.service; enabled; vendor preset: disabled)
     Active: active (running) since Thu 2021-03-11 08:55:28 PST; 2h 7min ago
    Process: 4451 ExecStartPre=/usr/lib/dirsrv/ds_systemd_ask_password_acl
       /etc/dirsrv/slapd-LDAP1/dse.ldif (code=exited, status=0/SUCCESS)
   Main PID: 4456 (ns-slapd)
     Status: "slapd started: Ready to process requests"
      Tasks: 26
     CGroup: /system.slice/system-dirsrv.slice/dirsrv@LDAP1.service
             └─4456 /usr/sbin/ns-slapd -D /etc/dirsrv/slapd-LDAP1 -i /run/dirsrv/slapd-LDAP1.pid

启动、停止和重启动 LDAP 服务器:

> sudo systemctl start dirsrv@LDAP1.service
> sudo systemctl stop dirsrv@LDAP1.service
> sudo systemctl restart dirsrv@LDAP1.service

有关使用 systemctl 的详细信息,请参见第 19 章 “systemd 守护程序

dsctl 命令还可启动和停止服务器:

> sudo dsctl LDAP1 status
> sudo dsctl LDAP1 stop
> sudo dsctl LDAP1 restart
> sudo dsctl LDAP1 start

5.3.5 配置用于本地管理的管理员身份凭证

要对 389 Directory Server 进行本地管理,您可以在 /root 目录中创建一个 .dsrc 配置文件,这样 root 和 sudo 用户管理服务器时就不必每运行一条命令都要键入连接细节。例 5.3 显示了在服务器上进行本地管理的示例,其中使用了 LDAP1com 作为后缀。

创建 /root/.dsrc 文件后,请尝试运行几条管理命令,例如创建新用户(参见第 5.6 节 “管理 LDAP 用户和组”)。

例 5.3︰ 用于本地管理的 .dsrc 文件
# /root/.dsrc file for administering the LDAP1 instance

[LDAP1] 1

uri = ldapi://%%2fvar%%2frun%%2fslapd-LDAP1.socket 2
basedn = dc=LDAP1,dc=COM
binddn = cn=Directory Manager

1

此处必须指定确切的实例名称。

2

ldapi 将检测尝试登录到服务器的用户的 UID 和 GID。如果 UID/GID 为 0/0dirsrv:dirsrv,则 ldapi 会将用户绑定为目录服务器的根 DN,即 cn=Directory Manager

在 URI 中,斜杠将替换为 %%2f,因此在本示例中,路径为 /var/run/slapd-LDAP1.socket

重要
重要:sudoers.ldap 中的新求反功能

在低于 1.9.9 的 sudo 版本中,sudoers.ldap 中的求反对于 sudoUsersudoRunAsUsersudoRunAsGroup 属性不起作用。例如:

 # does not match all but joe
# instead, it does not match anyone
sudoUser: !joe

# does not match all but joe
# instead, it matches everyone including Joe
sudoUser: ALL
sudoUser: !joe

sudo 1.9.9 和更高版本中,为 sudoUser 属性启用了求反。有关更多信息,请参见man 5 sudoers.ldap

5.4 防火墙配置

389 Directory Server 的默认 TCP 端口为 389 和 636。TCP 端口 389 用于未加密连接和 STARTTLS 连接。端口 636 用于通过 TLS 建立加密连接。

firewalldSUSE Linux Enterprise Desktop 的默认防火墙管理器。以下规则会激活 ldapldaps 防火墙服务:

> sudo firewall-cmd --add-service=ldap --zone=internal
> sudo firewall-cmd --add-service=ldaps --zone=internal
> sudo firewall-cmd --runtime-to-permanent

请将 zone 替换为您服务器的相应区域。有关使用 TLS 保护连接的信息,请参见第 5.10 节 “导入 TLS 服务器证书和密钥”;有关 第 23.3 节 “防火墙基础知识” 的信息,请参见firewalld

5.5 备份和恢复 389 Directory Server

389 Directory Server 支持脱机和联机备份。dsctl 命令可创建脱机数据库备份,dsconf 命令可创建联机数据库备份。备份 LDAP 服务器配置目录,以便在发生重大故障时能够完全恢复。

5.5.1 备份 LDAP 服务器配置

LDAP 服务器配置位于 /etc/dirsrv/slapd-INSTANCE_NAME 目录中。此目录包含证书、密钥和 dse.ldif 文件。使用 tar 命令创建此目录的压缩备份:

> sudo tar caf \
config_slapd-INSTANCE_NAME-$(date +%Y-%m-%d_%H-%M-%S).tar.gz \
/etc/dirsrv/slapd-INSTANCE_NAME/
注意
注意:可忽略的 tar 错误消息

运行 tar 时,您可能会看到可忽略的信息性消息 tar: Removing leading `/' from member names

要恢复以前的配置,请将其解压缩到同一目录:

  1. (可选) 要避免重写现有配置,请移动该配置:

    > sudo old /etc/dirsrv/slapd-INSTANCE_NAME/
  2. 解压缩备份存档:

    > sudo tar -xvzf \
    config_slapd-INSTANCE_NAME-DATE.tar.gz
  3. 将其复制到 /etc/dirsrv/slapd-INSTANCE_NAME

    > sudo cp -r etc/dirsrv/slapd-INSTANCE_NAME \
    /etc/dirsrv/slapd-INSTANCE_NAME

5.5.2 创建 LDAP 数据库的脱机备份并从该备份恢复

dsctl 命令可创建脱机备份。关闭服务器:

> sudo dsctl INSTANCE_NAME stop
Instance "INSTANCE_NAME" has been stopped

然后使用您的实例名称创建备份。以下示例在 /var/lib/dirsrv/slapd-INSTANCE_NAME/bak/INSTANCE_NAME-DATE 中创建备份存档:

> sudo dsctl INSTANCE_NAME db2bak
db2bak successful

例如,在名为 ldap1 的测试实例上,该命令如下所示:

/var/lib/dirsrv/slapd-ldap1/bak/ldap1-2021_10_25_13_03_17

从此备份进行恢复,并命名包含备份存档的目录:

> sudo dsctl INSTANCE_NAME bak2db \
/var/lib/dirsrv/slapd-INSTANCE_NAME/bak/INSTANCE_NAME-DATE/
bak2db successful

然后启动服务器:

> sudo dsctl INSTANCE_NAME start
Instance "INSTANCE_NAME" has been started

您还可以创建 LDIF 备份:

> sudo dsctl INSTANCE_NAME db2ldif --replication userRoot
ldiffile: /var/lib/dirsrv/slapd-INSTANCE_NAME/ldif/INSTANCE_NAME-userRoot-DATE.ldif
db2ldif successful

使用存档名称恢复 LDIF 备份,然后启动服务器:

> sudo dsctl ldif2db userRoot \
/var/lib/dirsrv/slapd-INSTANCE_NAME/ldif/INSTANCE_NAME-userRoot-DATE.ldif
> sudo dsctl INSTANCE_NAME start

5.5.3 创建 LDAP 数据库的联机备份并从该备份恢复

使用 dsconf 创建 LDAP 数据库的联机备份:

> sudo dsconf INSTANCE_NAME backup create
The backup create task has finished successfully

此命令会创建 /var/lib/dirsrv/slapd-INSTANCE_NAME/bak/INSTANCE_NAME-DATE

恢复该数据库:

> sudo dsconf INSTANCE_NAME backup restore \
/var/lib/dirsrv/slapd-INSTANCE_NAME/bak/INSTANCE_NAME-DATE

5.6 管理 LDAP 用户和组

使用 dsidm 命令创建、去除和管理用户与组。

5.6.1 查询现有的 LDAP 用户和组

以下示例演示如何列出现有的用户和组。这些示例使用实例名称 LDAP1。请将此名称替换为您的实例名称:

> sudo dsidm LDAP1 user list
> sudo dsidm LDAP1 group list

列出有关单个用户的所有信息:

> sudo dsidm LDAP1 user get USER

列出有关单个组的所有信息:

> sudo dsidm LDAP1 group get GROUP

列出组的成员:

> sudo dsidm LDAP1 group members GROUP

5.6.2 创建用户和管理口令

在以下示例中,我们将创建一个用户,即 wilber。示例服务器实例名为 LDAP1,该实例的后缀为 dc=LDAP1,dc=COM

过程 5.1︰ 创建 LDAP 用户

以下示例在您的 389 DS 实例上创建用户 Wilber Fox:

  1. > sudo dsidm LDAP1 user create --uid wilber \
      --cn wilber --displayName 'Wilber Fox' --uidNumber 1001 --gidNumber 101 \
      --homeDirectory /home/wilber
  2. 通过查询新用户的distinguished name(目录对象的完全限定名称,能够确保唯一)进行校验:

    > sudo dsidm LDAP1 user get wilber
    dn: uid=wilber,ou=people,dc=LDAP1,dc=COM
    [...]

    执行更改用户口令等操作时需要用到判别名。

  3. 为新用户 wilber 创建口令:

    1. > sudo dsidm LDAP1 account reset_password \
        uid=wilber,ou=people,dc=LDAP1,dc=COM
    2. 输入 wilber 的新口令两次。

      如果操作成功,您将看到以下消息:

      reset password for uid=wilber,ou=people,dc=LDAP1,dc=COM

      使用相同的命令更改现有口令。

  4. 校验用户的口令是否有效:

    > ldapwhoami -D uid=wilber,ou=people,dc=LDAP1,dc=COM -W
    Enter LDAP Password: PASSWORD
    dn: uid=wilber,ou=people,dc=LDAP1,dc=COM

5.6.3 创建和管理组

创建用户后,您可以创建组,然后将用户分配到这些组。在以下示例中,我们将创建 server_admins 组,并将 wilber 用户分配到此组。示例服务器实例名为 LDAP1,该实例的后缀为 dc=LDAP1,dc=COM

过程 5.2︰ 创建 LDAP 组并将用户分配到其中
  1. 创建组:

    > sudo dsidm LDAP1 group create

    系统会提示您输入组名。输入您选择的组名,在以下示例中为 SERVER_ADMINS

    Enter value for cn : SERVER_ADMINS
  2. 将用户 wilber(在过程 5.1 “创建 LDAP 用户”中创建)添加到组中:

    > sudo dsidm LDAP1 group add_member SERVER_ADMINS \
    uid=wilber,ou=people,dc=LDAP1,dc=COM
    added member: uid=wilber,ou=people,dc=LDAP1,dc=COM

5.6.4 删除用户和组以及从组中去除用户

使用 dsidm 命令可以删除用户、从组中去除用户,以及删除组。以下示例从 server_admins 组中去除示例用户 wilber:

> sudo dsidm LDAP1 group remove_member SERVER_ADMINS \
uid=wilber,ou=people,dc=LDAP1,dc=COM

删除用户:

> sudo dsidm LDAP1 user delete \
uid=wilber,ou=people,dc=LDAP1,dc=COM

删除组:

> sudo dsidm LDAP1 group delete SERVER_ADMINS

5.7 管理插件

使用以下命令可列出所有已启用和已禁用的可用插件。使用服务器的主机名而不是 389 Directory Server 的实例名称,例如,以下示例使用了主机名 LDAPSERVER1

> sudo dsconf -D "cn=Directory Manager" ldap://LDAPSERVER1 plugin list
Enter password for cn=Directory Manager on ldap://LDAPSERVER1: PASSWORD

7-bit check
Account Policy Plugin
Account Usability Plugin
ACL Plugin
ACL preoperation
[...]

以下命令会启用第 5.8 节 “使用 SSSD 管理 LDAP 身份验证”中提到的 MemberOf 插件。MemberOf 可以简化用户搜索,使用该插件,只需运行一条命令就能返回用户及其所属的任何组。如果不使用 MemberOf 的话,客户端必须运行多次查找才能找到用户的组成员资格。

> sudo dsconf -D "cn=Directory Manager" ldap://LDAPSERVER1 plugin memberof enable

命令中使用的插件名称是小写的,因此这些名称与您列出插件时显示的名称不同。如果错误地输入了插件名称,您将看到有用的错误消息:

dsconf instance plugin: error: invalid choice: 'MemberOf' (choose from
'memberof', 'automember', 'referential-integrity', 'root-dn', 'usn',
'account-policy', 'attr-uniq', 'dna', 'linked-attr', 'managed-entries',
'pass-through-auth', 'retro-changelog', 'posix-winsync', 'contentsync', 'list',
'show', 'set')

启用插件后,需要重启动服务器:

> sudo systemctl restart dirsrv@LDAPSERVER1.service

接下来配置插件。以下示例启用 MemberOf 来搜索所有项。请使用您的实例名称而不是服务器的主机名:

> sudo dsconf LDAP1 plugin memberOf set --scope dc=example,dc=com
Successfully changed the cn=MemberOf Plugin,cn=plugins,cn=config

启用并配置 MemberOf 插件后,所有新组和用户将自动成为 MemberOf 目标。但是,在启用该插件之前存在的任何用户和组不会自动成为 MemberOf 目标。必须手动标记这些用户和组:

> sudo dsidm LDAP1 user modify suzanne add:objectclass:nsmemberof
Successfully modified uid=suzanne,ou=people,dc=ldap1,dc=com

现在,只需运行一条命令即可列出 suzanne 的信息和组成员资格:

> sudo dsidm LDAP1 user get suzanne
dn: uid=suzanne,ou=people,dc=ldap1,dc=com
cn: suzanne
displayName: Suzanne Geeko
gidNumber: 102
homeDirectory: /home/suzanne
memberOf: cn=SERVER_ADMINS,ou=groups,dc=ldap1,dc=com

修改大量用户是一个繁重的任务。以下示例显示如何使用一条 fixup 命令使所有旧用户成为 MemberOf 目标:

> sudo dsconf LDAP1 plugin memberof fixup -f '(objectClass=*)' dc=LDAP1,dc=COM

5.7.1 389 Directory Server 不支持的插件

389 Directory Server 不支持以下插件:

  • Distributed Numeric Assignment (DNA) 插件

  • Managed Entries Plug-in (MEP)

  • Posix Winsync 插件

5.8 使用 SSSD 管理 LDAP 身份验证

系统安全服务守护程序 (SSSD) 可管理远程用户的身份验证、标识和访问控制。本节介绍如何使用 SSSD 来管理 389 Directory Server 的身份验证和标识。

SSSD 可在 LDAP 服务器和客户端之间进行调解。它支持多个提供者后端,例如 LDAP、Active Directory 和 Kerberos。SSSD 支持 SSH、PAM、NSS 和 sudo 等服务。SSSD 通过缓存用户 ID 和凭据来提供性能优势与恢复能力。缓存可以减少向 389 DS 服务器发出的请求数量,并在后端不可用时提供身份验证和身份服务。

如果名称服务缓存守护程序 (nscd) 在您的网络中运行,您应该将其禁用或去除。nscd 仅缓存 passwd、group、hosts、service 和 netgroup 等常见名称服务请求,并且会与 SSSD 冲突。

LDAP 服务器是提供者,SSSD 实例是提供者的客户端。可以在 389 DS 服务器上安装 SSSD,但将其安装在单独的计算机上可以提供一定的复原能力,以防 389 DS 服务器不可用。请按照以下过程安装和配置 SSSD 客户端。示例 389 DS 实例名称为 LDAP1

  1. 安装 sssdsssd-ldap 软件包。

    > sudo zypper in sssd sssd-ldap
  2. 备份 /etc/sssd/sssd.conf 文件(如果存在):

    > sudo old /etc/sssd/sssd.conf
  3. 创建新的 SSSD 配置模板。允许的输出文件名为 sssd.confldap.confdisplay 将输出发送到 stdout。以下示例在 /etc/sssd/sssd.conf 中创建客户端配置:

    > sudo cd /etc/sssd
    > sudo dsidm LDAP1 client_config sssd.conf
  4. 检查输出,并根据您的环境进行任何必要的更改。以下 /etc/sssd/sssd.conf 文件演示了一个可正常工作的示例。

    重要
    重要:MemberOf

    LDAP 访问过滤器依赖于所要配置的 MemberOf。有关详细信息,请参见第 5.7 节 “管理插件”

    [sssd]
    services = nss, pam, ssh, sudo
    config_file_version = 2
    domains = default
    
    [nss]
    homedir_substring = /home
    
    [domain/default]
    # If you have large groups (for example, 50+ members),
    # you should set this to True
    ignore_group_members = False
    debug_level=3
    cache_credentials = True
    id_provider = ldap
    auth_provider = ldap
    access_provider = ldap
    chpass_provider = ldap
    
    ldap_schema = rfc2307bis
    ldap_search_base = dc=example,dc=com
    # We strongly recommend ldaps
    ldap_uri = ldaps://ldap.example.com
    ldap_tls_reqcert = demand
    ldap_tls_cacert = /etc/openldap/ldap.crt
    ldap_access_filter = (|(memberof=cn=<login group>,ou=Groups,dc=example,dc=com))
    enumerate = false
    access_provider = ldap
    
    ldap_user_member_of = memberof
    ldap_user_gecos = cn
    ldap_user_uuid = nsUniqueId
    ldap_group_uuid = nsUniqueId
    ldap_account_expire_policy = rhds
    ldap_access_order = filter, expire
    # add these lines to /etc/ssh/sshd_config
    #  AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
    #  AuthorizedKeysCommandUser nobody
    ldap_user_ssh_public_key = nsSshPublicKey
  5. 将文件所有权设置为 root,并限制只有 root 具有读写权限:

    > sudo chown root:root /etc/sssd/sssd.conf
    > sudo chmod 600 /etc/sssd/sssd.conf
  6. 编辑 SSSD 服务器上的 /etc/nsswitch.conf 配置文件,在其中包含以下行:

    passwd: compat sss
    group:  compat sss
    shadow: compat sss
  7. 编辑 SSSD 服务器上的 PAM 配置,修改其中的 common-account-pccommon-auth-pccommon-password-pccommon-session-pcSUSE Linux Enterprise Desktop 提供了用于一次性修改所有这些文件的 pam-config 命令:

    > sudo pam-config -a --sss
  8. 校验修改后的配置:

    > sudo pam-config -q --sss
    auth:
    account:
    password:
    session:
  9. 将 389 DS 服务器中的 /etc/dirsrv/slapd-LDAP1/ca.crt 复制到 SSSD 服务器上的 /etc/openldap/certs,然后为其重建哈希:

    > sudo c_rehash /etc/openldap/certs
  10. 启用并启动 SSSD:

    > sudo systemctl enable --now sssd

有关使用 systemctl 管理 sssd.service 的信息,请参见第 4 章 “使用 YaST 设置身份验证客户端

5.8.1 不支持的口令哈希和身份验证方案

不支持将以下各项作为 dse.ldifnsslapd-rootpwstorageschemepasswordStorageScheme 设置的配置值,也不支持作为帐户策略对象中 passwordStorageScheme 的值:

  • SHA

  • SSHA

  • SHA256

  • SSHA256

  • SHA384

  • SSHA384

  • SHA512

  • SSHA512

  • NS-MTA-MD5

  • clear

  • MD5

  • SMD5

注意
注意

如果 nsslapd-enable-upgrade-hash 设置为 on(默认为 on),支持包含这些值的数据库导入项。

5.9 从 OpenLDAP 迁移到 389 Directory Server

从 SUSE Linux Enterprise 15 SP3 开始,OpenLDAP 已弃用且不再受支持。它已由 389 Directory Server 取代。SUSE 提供了 openldap_to_ds 实用程序用于帮助迁移,该实用程序随附在 389-ds 软件包中。

openldap_to_ds 实用程序会自动执行尽可能多的迁移工作。但是,每个 LDAP 部署各不相同,因此我们无法开发适合所有情况的工具。请在必要时进行干预并执行手动步骤。此外还需在尝试进行生产迁移之前全面测试您的迁移过程。

重要
重要:查看 help 页面

在使用 openldap_to_ds 迁移工具之前,强烈建议您查看 openldap_to_ds ‑‑help 的输出。它有助于您了解迁移工具的功能和限制,并防止您做出错误的假设。

5.9.1 测试从 OpenLDAP 迁移

由于 OpenLDAP 与 389 Directory Server 的差异非常大,因此需要对迁移进行反复测试和调整。执行快速迁移测试会很有帮助,这样可大致了解需要执行哪些步骤才能确保迁移成功。

先决条件:

  • 正在运行的 389 Directory Server 实例

  • 采用动态 ldif 格式的 OpenLDAP slapd 配置文件或目录

  • OpenLDAP 数据库的 ldif 文件备份

如果您的 slapd 配置不是动态 ldif 格式,请使用 slaptest 创建动态副本。创建一个 slapd.d 目录(例如 /root/slapd.d/),然后运行以下命令:

> sudo slaptest -f /etc/openldap/slapd.conf -F /root/slapd.d

这会生成几个类似于以下示例的文件:

> sudo ls /root/slapd.d/*

/root/slapd.d/cn=config.ldif

/root/slapd.d/cn=config:
cn=module{0}.ldif  cn=schema.ldif                 olcDatabase={0}config.ldif
cn=schema          olcDatabase={-1}frontend.ldif  olcDatabase={1}mdb.ldif

为每个后缀创建一个 ldif 文件。在以下示例中,后缀为 dc=LDAP1,dc=COM。如果您使用的是 /etc/openldap/slapd.conf 格式,请运行以下命令创建 ldif 备份文件:

> sudo slapcat -f /etc/openldap/slapd.conf -b dc=LDAP1,dc=COM \
-l /root/LDAP1-COM.ldif

使用 openldap_to_ds 分析配置和文件,并显示迁移计划而不更改任何内容:

> sudo openldap_to_ds LDAP1\
/root/slapd.d /root/LDAP1-COM.ldif.ldif

这会执行试运行,但不更改任何内容。输出如下所示:

Examining OpenLDAP Configuration ...
Completed OpenLDAP Configuration Parsing.
Examining Ldifs ...
Completed Ldif Metadata Parsing.
The following migration steps will be performed:
 * Schema Skip Unsupported Attribute -> otherMailbox (0.9.2342.19200300.100.1.22)
 * Schema Skip Unsupported Attribute -> dSAQuality (0.9.2342.19200300.100.1.49)
 * Schema Skip Unsupported Attribute -> singleLevelQuality (0.9.2342.19200300.100.1.50)
 * Schema Skip Unsupported Attribute -> subtreeMinimumQuality (0.9.2342.19200300.100.1.51)
 * Schema Skip Unsupported Attribute -> subtreeMaximumQuality (0.9.2342.19200300.100.1.52)
 * Schema Create Attribute -> suseDefaultBase (SUSE.YaST.ModuleConfig.Attr:2)
 * Schema Create Attribute -> suseNextUniqueId (SUSE.YaST.ModuleConfig.Attr:3)
[...]
 * Schema Create ObjectClass -> suseDhcpConfiguration (SUSE.YaST.ModuleConfig.OC:10)
 * Schema Create ObjectClass -> suseMailConfiguration (SUSE.YaST.ModuleConfig.OC:11)
 * Database Reindex -> dc=example,dc=com
 * Database Import Ldif -> dc=example,dc=com from example.ldif -
excluding entry attributes = [{'structuralobjectclass', 'entrycsn'}]
No actions taken. To apply migration plan, use '--confirm'

以下示例会执行迁移,其输出与试运行后的输出不同:

  > sudo openldap_to_ds LDAP1 /root/slapd.d /root/LDAP1-COM.ldif --confirm
Starting Migration ... This may take some time ...
migration: 1 / 40 complete ...
migration: 2 / 40 complete ...
migration: 3 / 40 complete ...
[...]
Index task index_all_05252021_120216 completed successfully
post: 39 / 40 complete ...
post: 40 / 40 complete ...
🎉 Migration complete!
----------------------
You should now review your instance configuration and data:
 * [ ] - Create/Migrate Database Access Controls (ACI)
 * [ ] - Enable and Verify TLS (LDAPS) Operation
 * [ ] - Schedule Automatic Backups
 * [ ] - Verify Accounts Can Bind Correctly
 * [ ] - Review Schema Inconistent ObjectClass -> pilotOrganization (0.9.2342.19200300.100.4.20)
 * [ ] - Review Database Imported Content is Correct -> dc=ldap1,dc=com

迁移完成后,openldap_to_ds 会创建必须完成的迁移后任务核对清单。最好记录迁移后步骤,以便可以在后期生产过程中再现这些步骤。然后测试客户端和应用程序与迁移后 389 Directory Server 实例的集成。

重要
重要:制定回滚计划

制定回滚计划以防发生任何失败。此计划应该定义成功迁移的要素、用于确定哪些方面正常以及哪些方面需要修复的测试、至关重要的步骤、可以推迟的事项、如何确定何时撤消更改、如何在尽量减少服务中断的情况下撤消更改,以及其他哪些团队需要参与迁移。

由于部署的可变性,很难提供成功进行生产迁移的通用方法。在全面测试迁移过程并确认结果正常后,以下常规步骤将有助于:

  • 在做出更改之前的 48 小时将所有主机名/DNS TTL 减少至 5 分钟,以便能够快速回滚到现有的 OpenLDAP 部署。

  • 暂停所有数据同步和传入数据过程,以确保 OpenLDAP 环境中的数据在迁移期间不会更改。

  • 在迁移之前准备好所有要部署 389 Directory Server 的主机。

  • 准备好测试迁移文档。

5.9.2 测试使用 saslauthd 的 OpenLDAP 服务器迁移

在 OpenLDAP 部署中,常会使用 saslauthd 来进行用户的直通身份验证。身份验证过程涉及以下组件:

 ┌─────────────────┐
 │                 │
 │   LDAP client   │
 │                 │
 └─────────────────┘
          │
      binds to
          │
          ▼
 ┌─────────────────┐
 │    OpenLDAP     │
 │     server      │
 │                 │
 └─────────────────┘
          │
          │
          ▼
 ┌─────────────────┐
 │                 │
 │    saslauthd    │
 │                 │
 └─────────────────┘
          │
          │
          ▼
 ┌─────────────────┐
 │                 │
 │  External auth  │
 │                 │
 └─────────────────┘

为了检查配置的正确性以及以后进行故障排除,务必要了解以下信息:

  • 如果 userPassword 属性的值采用 userPassword: {SASL}USERNAME@REALM 格式,则 OpenLDAP 会发现允许对用户进行直通身份验证。前提是要构建 OpenLDAP 服务器,并设置 --enable-spasswd 选项以启用直通身份验证。

  • OpenLDAP 通过 /usr/lib/sasl2/slapd.conf 配置与 saslauthd 的连接。

  • saslauthd 会使用 /etc/sysconfig/saslauthd 中配置的命令行参数来发现相关模块。

  • saslauthd 的后端模块则使用自己的配置(如 man saslauthd 中所述)。

有关使用 OpenLDAP 的直通身份验证的详细信息,请参见官方 OpenLDAP 管理指南

5.9.2.1 将 SASL 直通身份验证从 OpenLDAP 迁移到 389 Directory Server

为遵循将 SASL 直通身份验证从 OpenLDAP 正确迁移到 389 Directory Server 的最佳实践,请按照以下步骤操作:

  1. 在迁移之前,确保您可以在 OpenLDAP 服务器上成功运行 testsaslauthd

    > sudo testsaslauthd -u USERNAME@REALM -p PASSWORD

    该领域会将身份验证路由到 saslauthd 中的正确后端,然后使用用户名来检查身份。

  2. 安装可使 389 Directory Server 能与 saslauthd 连接的软件包 pam_saslauthd

    > sudo zypper install -y pam_saslauthd
  3. 运行 openldap_to_ds 命令行工具从 OpenLDAP 迁移到 389 Directory Server。有关该迁移过程的详细信息,请参见第 5.9.1 节 “测试从 OpenLDAP 迁移”

    注意
    注意

    openldap_to_ds 进程运行时,如果检测到某用户 userPssword 属性的值采用 userPassword: {SASL}USERNAME@REALM 格式,则会将该值去除并设置为 nsSaslauthId 属性的值(采用 nsSaslauthId: USERNAME@REALM 格式)。此外,系统会自动添加属性值 objectClass: nsSaslauthAccount 以支持修改。

  4. 迁移完成后,运行以下命令检查是否正确配置了 PAM 直通身份验证:

    > sudo dsconf INSTANCE plugin pam-pass-through-auth show
    > sudo dsconf INSTANCE plugin pam-pass-through-auth list

成功迁移后,直通身份验证流程涉及以下组件:

  ┌─────────────────┐
  │                 │
  │   LDAP client   │
  │                 │
  └─────────────────┘
           │
       binds to
           │
           ▼
  ┌─────────────────┐
  │     389-DS      │
  │     server      │
  │                 │
  └─────────────────┘
           │
           ▼
  ┌─────────────────┐
  │                 │
  │  pam saslauthd  │
  │                 │
  └─────────────────┘
           │
           ▼
  ┌─────────────────┐
  │                 │
  │    saslauthd    │
  │                 │
  └─────────────────┘
           │
           │
           ▼
  ┌─────────────────┐
  │                 │
  │  External auth  │
  │                 │
  └─────────────────┘

5.9.2.2 saslauthd 直通身份验证查错

要对从 OpenLDAP 迁移到 389 Directory Server 之前和之后的 saslauthd 直通身份验证问题查错,请参见以下提示:

确保 testsaslauthd 适用于 USERNAME@REALM

请参见第 5.9.2 节 “测试使用 saslauthd 的 OpenLDAP 服务器迁移”中运行 testsaslauthd 的步骤。

如果出现问题,请尝试以下方法:

  • 检查 /etc/sysconfig/saslauthd,确保 saslauthd 后端模块配置正确。有关 saslauthd 后端模块及其配置的详细信息,请运行 man saslauthd

  • /etc/sysconfig/saslauthd 中添加 SASLAUTHD_PARAMS="-d" 以启用调试日志记录。

  • 查看 journalctl 命令输出中的 saslauthd 日志。

确保 PAM saslauthd 可正常工作。

要检查 PAM saslauthd 是否正常工作,您可以使用 https://github.com/kanidm/pam_tester 上提供的 pam_tester 工具。

注意
注意

pam_tester 工具不受官方支持。

确保已启用 PAM Pass Through Auth 插件。

运行以下命令检查 PAM Pass Through Auth 插件的状态:

> sudo dsconf INSTANCE plugin pam-passt-through-auth status

要启用该插件,请运行以下命令:

> sudo dsconf INSTANCE plugin pam-pass-through-auth enable
检查 PAM Pass Through Auth 插件的配置。

要检查服务器实例的 PAM Pass Through Auth 插件配置,请运行以下命令:

> sudo dsconf INSTANCE plugin pam-pass-through-auth show
检查服务器实例的用户错误日志。

检查 /var/lib/SERVER_USER_NAME/INSTANCE/error 中的日志。

5.9.3 规划迁移

由于 OpenLDAP 如同一个零件箱且高度可自定义,因此无法制定出放之四海皆准的迁移计划。因而有必要针对 OpenLDAP 和其他集成评估您的当前环境和配置。这包括但不限于:

  • 复制拓扑

  • 高可用性和负载平衡器配置

  • 外部数据流(IGA、HR、AD 等)

  • 配置的叠加组件(389 Directory Server 中的插件)

  • 客户端配置和预期的服务器功能

  • 自定义纲要

  • TLS 配置

规划 389 Directory Server 部署的最终大致结果。此项规划包含的内容与上面的列表相同,不过需要将叠加组件替换为插件。评估当前环境并规划您预期的 389 Directory Server 环境后,便可以制定迁移计划。建议构建与 OpenLDAP 环境并行的 389 Directory Server 环境,以便可以在两者之间切换。

从 OpenLDAP 迁移到 389 Directory Server 属于单向迁移。两者之间的差异相当大,因此它们不可互操作,并且不存在从 389 Directory Server 到 OpenLDAP 的迁移路径。下表重点指出了两者的主要相似和不同之处。

功能OpenLDAP389 Directory Server兼容
双向复制SyncREPL特定于 389 DS 的系统
MemberOf叠加组件插件是,仅限简单配置
外部身份验证代理-
Active Directory 同步-Winsync 插件
内置纲要OLDAP 纲要389 Directory Server 纲要是,受迁移工具支持
自定义纲要OLDAP 纲要389 Directory Server 纲要是,受迁移工具支持
数据库导入LDIFLDIF是,受迁移工具支持
口令哈希不确定不确定是,支持除 Argon2 以外的所有格式
OpenLDAP 到 389 DS 的复制--不提供用于复制到 389 DS 的机制
基于时间的一次性口令 (TOTP)TOTP 叠加组件-否,目前不支持
entryUUIDOpenLDAP 的组成部分插件

5.10 导入 TLS 服务器证书和密钥

可以使用以下命令行工具管理 389 Directory Server 的 CA 证书和密钥:certutilopensslpk12util

可以使用在您创建新的 389 DS 实例时由 dscreate 创建的自我签名证书进行测试。在 /etc/dirsrv/slapd-INSTANCE-NAME/ca.crt 中可以找到该证书。

对于生产环境,最佳实践是使用第三方证书颁发机构,例如 Let's Encrypt、CAcert.org、SSL.com 或您选择的任何 CA。请求服务器证书、客户端证书和根证书。

重要
重要

Mozilla NSS(网络安全服务)工具包会使用证书存储区中所含证书的昵称。服务器证书使用昵称 Server-Cert

  1. 使用以下命令从实例中去除 Self-Signed-CA 和 Server-Cert:

    > sudo dsctl INSTANCE_NAME tls remove-cert Self-Signed-CA
    > sudo dsctl INSTANCE_NAME tls remove-cert Server-Cert
    

    INSTANCE_NAME 替换为目录服务器的实例名称。在前几节中,该名称就是 LDAP1。

  2. 导入为您的证书签名的 CA。

    > sudo sudo dsctl INSTANCE_NAME tls import-ca
       /path/to/CA/in/PEM/format/CA.pem  NICKNAME_FOR_CA
    

    INSTANCE_NAME 替换为目录服务器的实例名称。将 /path/to/CA/in/PEM/format/CA.pem 替换为 PEM 格式的 CA 证书文件的完整路径。将 NICKNAME_FOR_CA 替换为 CA 的昵称。

  3. 导入服务器证书和证书的密钥。

    > sudo dsctl INSTANCE_NAME tls import-server-key-cert
      /path/to/SERVER.pem /path/to/SERVER.key

    INSTANCE_NAME 替换为目录服务器的实例名称。将 /path/to/SERVER.pem 替换为 PEM 格式的服务器证书的完整路径。将 /path/to/SERVER.key 替换为 PEM 格式的服务器证书密钥文件的完整路径。

  4. 重启动实例,以使用新证书。

    > sudo systemctl restart dirsrv@INSTANCE-NAME..service
    

    INSTANCE_NAME 替换为目录服务器的实例名称。

5.11 设置复制

389 Directory Server 支持在多个服务器之间复制其数据库内容。根据复制类型,389 Directory Server 提供:

  • 更好的性能和更快的响应速度

  • 容错和故障转移

  • 负载平衡

  • 高可用性

数据库是可复制的最小目录单位。您可以复制整个数据库,但无法复制数据库中的子树。一个数据库必须对应于一个后缀。无法复制分布在两个或更多个数据库之间的后缀。

将数据发送到另一个复本的复本是提供者。从提供者接收数据的复本是使用者。复制始终由提供者发起,单个提供者可以向多个使用者发送数据。提供者是一个读写复本,而使用者是只读的,在进行多提供者复制的情况下除外。在多提供者复制中,提供者既是数据的提供者,也是该数据的使用者。

5.11.1 异步写入

389 DS 管理复制的方式不同于其他数据库。复制是异步的,但最终会保持一致。也就是说:

  • 会立即接受对单个服务器的任何写入或更改。

  • 在一台服务器上完成写入后,要经过一定的延迟,写入内容才会复制到其他服务器并显示在其中。

  • 如果该写入操作与其他服务器上的写入操作冲突,该写入操作在将来的某个时间点可能回滚。

  • 由于存在复制延迟,并非所有服务器都可以同时显示相同的内容。

由于 LDAP 属于小规模写入,这些因素意味着所有服务器至少符合已知一致状态的公共基线。在此基线的基础上只会发生轻微的变化,因此延迟复制的上述许多特征在日常使用中不会被察觉到。

5.11.2 设计拓扑

在设计复制拓扑时请考虑以下因素。

  • 复制需求:高可用性、地理位置、读取缩放或所有这些因素的组合。

  • 您打算在拓扑中使用多少个复本(节点、服务器)。

  • 数据流的方向,这包括拓扑内部的数据,以及流入拓扑的数据。

  • 客户端如何在拓扑节点之间根据其请求进行平衡(多个 LDAP URI、SRV 记录、负载平衡器)。

这些因素都会影响您创建拓扑的方式。(有关拓扑示例,请参见第 5.11.3 节 “复制拓扑示例”。)

5.11.3 复制拓扑示例

以下章节提供了使用两到六个 389 Directory Server 节点的复制拓扑示例。拓扑中支持的最大提供者复本数量为 20 个。操作经验表明,实现高效复制的最佳数量最多为 8 个。

5.11.3.1 两个复本

例 5.4︰ 两个提供者复本
┌────┐       ┌────┐
│ S1 │◀─────▶│ S2 │
└────┘       └────┘

例 5.4 “两个提供者复本”中有两个复本(S1 和 S2),它们互相双向复制,因此它们既是提供者,也是使用者。S1 和 S2 可位于不同的数据中心,也可位于同一个数据中心。客户端可以使用 LDAP URI、负载平衡器或 DNS SRV 记录在服务器之间进行平衡。这是可实现高可用性的最简单拓扑。每个服务器需要能够提供 100% 的客户端负载,以防其他服务器出于任何原因脱机。双节点复制一般不足以实现横向读取缩放,因为如果另一个节点脱机,单个节点将处理所有读取请求。

注意
注意:默认拓扑

应将双节点拓扑视为默认拓扑,因为它最容易管理。随着时间的推移,您可以根据需要扩展拓扑。

5.11.3.2 四个提供者复本

例 5.5︰ 四个提供者复本
┌────┐       ┌────┐
│ S1 │◀─────▶│ S2 │
└────┘       └────┘
   ▲            ▲
   │            │
   ▼            ▼
┌────┐       ┌────┐
│ S3 │◀─────▶│ S4 │
└────┘       └────┘

例 5.5 “四个提供者复本”中有四个相互同步的提供者复本。这些复本可以位于四个数据中心,或者每个数据中心包含两个服务器。在每个数据中心包含一个节点的情况下,每个节点应该能够支持 100% 的客户端负载。如果每个数据中心包含两个节点,每个节点只需缩放到 50% 的客户端负载。

5.11.3.3 六个复本

例 5.6︰ 六个复本
                  ┌────┐       ┌────┐
                  │ S1 │◀─────▶│ S2 │
                  └────┘       └────┘
                     ▲            ▲
                     │            │
   ┌────────────┬────┴────────────┴─────┬────────────┐
   │            │                       │            │
   ▼            ▼                       ▼            ▼
┌────┐       ┌────┐                  ┌────┐       ┌────┐
│ S3 │◀─────▶│ S4 │                  │ S5 │◀─────▶│ S6 │
└────┘       └────┘                  └────┘       └────┘

例 5.6 “六个复本”中,每个对位于不同的位置。S1 和 S2 是提供者,S3、S4、S5 和 S6 是 S1 和 S2 的使用者。每一对服务器相互复制。S3、S4、S5 和 S6 可接受写入,不过,大部分复制工作是通过 S1 和 S2 完成的。此设置提供地理隔离来实现高可用性和缩放。

5.11.3.4 具有只读使用者的六个复本

例 5.7︰ 具有只读使用者的六个复本
             ┌────┐       ┌────┐
             │ S1 │◀─────▶│ S2 │
             └────┘       └────┘
                │            │
                │            │
   ┌────────────┼────────────┼────────────┐
   │            │            │            │
   ▼            ▼            ▼            ▼
┌────┐       ┌────┐       ┌────┐       ┌────┐
│ S3 │       │ S4 │       │ S5 │       │ S6 │
└────┘       └────┘       └────┘       └────┘

例 5.7 “具有只读使用者的六个复本”中,S1 和 S2 是提供者,其他四个服务器是只读使用者。所有更改在 S1 和 S2 上发生,并传播到四个复本。只读使用者可以配置为仅存储数据库的子集或部分项,以限制数据透露。例如,您可以在 DMZ 中部署一个不完整的只读服务器,这样,如果数据透露,更改就无法传播回其他复本。

5.11.4 术语

在示例拓扑中可以看到,389 DS 可以在拓扑中充当多个角色。以下列表阐明了术语。

复本

包含附加数据库的 389 DS 实例。

读写复本

包含整个数据库的复本,接受读取和写入操作。

只读复本

包含整个数据库的复本,仅接受读取操作。

不完整的只读复本

包含部分数据库的复本,仅接受只读操作。

提供者

将其数据库中的数据提供给另一个复本的复本。

使用者

从另一个复本接收数据以写入自身数据库的复本。

复制协议

用于定义其提供者和使用者与另一个复本的关系的服务器配置。

拓朴

通过复制协议连接的一组复本。

复本 ID

389 Directory Server 实例在复制拓扑中的唯一标识符。

复制管理者

在目录中拥有复制权限的帐户。

5.11.5 配置复制

第一个示例使用单个只读服务器设置双节点双向复制,这是一个极简的起点示例。在以下示例中,两个读写节点的主机名分别为 RW1 和 RW2,只读服务器为 RO1。(使用您自己的主机名。)

所有服务器都应有一个后缀相同的后端。只有一个服务器 (RW1) 需要数据库的初始副本。

5.11.5.1 配置双节点复制

以下命令使用主机名 RW1 和 RW2 在双节点设置 (例 5.4 “两个提供者复本”) 中配置读写复本。(使用您自己的主机名。)

警告
警告:创建强复制管理者口令

在安全性和访问权限方面,应以等同于目录管理者的方式来对待复制管理者,并且应为其创建强口令。

如果您为每个服务器创建不同的复制管理者口令,请务必跟踪哪个口令属于哪个服务器。例如,在 RW1 的复制协议中配置出站连接时,需要将复制管理者口令设置为 RW2 复制管理者口令。

首先配置 RW1:

> sudo dsconf INSTANCE-NAME replication create-manager
> sudo dsconf INSTANCE-NAME replication enable \
--suffix dc=example,dc=com \
--role supplier --replica-id 1 --bind-dn "cn=replication manager,cn=config"

配置 RW2:

> sudo dsconf INSTANCE-NAME replication create-manager
> sudo dsconf INSTANCE-NAME replication enable \
--suffix dc=example,dc=com \
--role supplier --replica-id 2 --bind-dn "cn=replication manager,cn=config"

这会创建 RW1 和 RW2 中所需的复制元数据。请注意两个服务器的 replica-id 的差异。这还会创建复制管理者帐户,该帐户拥有复制权限,可以在两个节点之间进行身份验证。

RW1 和 RW2 现在都已配置为包含复制元数据。下一步是为从 RW1 流向 RW2 的出站数据创建第一个协议。

> sudo dsconf INSTANCE-NAME repl-agmt create \
--suffix dc=example,dc=com \
--host=RW2 --port=636 --conn-protocol LDAPS --bind-dn "cn=replication manager,cn=config" \
--bind-passwd PASSWORD --bind-method SIMPLE RW1_to_RW2

只有在完全同步数据库之后,数据才会从 RW1 流向 RW2,这称为初始化或重新初始化。这会重置 RW2 上的所有数据库内容,以便与 RW1 的内容匹配。运行以下命令来触发数据重新初始化:

> sudo dsconf INSTANCE-NAME repl-agmt init \
--suffix dc=example,dc=com RW1_to_RW2

在 RW1 上运行以下命令来检查状态:

> sudo dsconf INSTANCE-NAME repl-agmt init-status \
--suffix dc=example,dc=com RW1_to_RW2

此命令完成后,您应会看到消息 Agreement successfully initialized。如果收到错误消息,请检查错误日志。否则,应会在 RW2 上看到与 RW1 中相同的内容。

最后,为了将这种复制设置为双向复制,请配置一个从 RW2 出站复制到 RW1 的复制协议:

> sudo dsconf INSTANCE-NAME repl-agmt create \
--suffix dc=example,dc=com \
--host=RW1 --port=636 --conn-protocol LDAPS \
--bind-dn "cn=replication manager,cn=config" --bind-passwd PASSWORD \
--bind-method SIMPLE RW2_to_RW1

现在,在 RW1 或 RW2 上做出的更改将复制到另一个节点。使用以下命令检查任一服务器上的复制状态:

> sudo dsconf INSTANCE-NAME repl-agmt status \
--suffix dc=example,dc=com \
--bind-dn "cn=replication manager,cn=config" \
--bind-passwd PASSWORD RW2_to_RW1

5.11.5.2 配置只读节点

要创建只读节点,首先需创建复制管理者帐户和元数据。示例服务器的主机名为 RO3:

警告
警告:创建强复制管理者口令

在安全性和访问权限方面,应以等同于目录管理者的方式来对待复制管理者,并且应为其创建强口令。

如果您为每个服务器创建不同的复制管理者口令,请务必跟踪哪个口令属于哪个服务器。例如,在 RW1 的复制协议中配置出站连接时,需要将复制管理者口令设置为 RW2 复制管理者口令。

> sudo dsconf INSTANCE_NAME replication create-manager
> sudo  dsconf INSTANCE_NAME \
replication enable --suffix dc=EXAMPLE,dc=COM \
--role consumer --bind-dn "cn=replication manager,cn=config"

对于只读复本,请不要提供复本 ID,并将角色设置为 consumer。这会为所有只读复本分配一个特殊的只读复本 ID。创建只读复本后,将 RW1 和 RW2 中的复制协议添加到只读实例。以下示例在 RW1 上运行:

> sudo dsconf INSTANCE_NAME \
repl-agmt create --suffix dc=EXAMPLE,dc=COM \
--host=RO3 --port=636 --conn-protocol LDAPS \
--bind-dn "cn=replication manager,cn=config" --bind-passwd PASSWORD
--bind-method SIMPLE RW1_to_RO3

以下示例会在 RW2 上配置 RW2 与 RO3 之间的复制协议:

> sudo dsconf INSTANCE_NAME repl-agmt create \
--suffix dc=EXAMPLE,dc=COM \
--host=RO3 --port=636 --conn-protocol LDAPS \
--bind-dn "cn=replication manager,cn=config" --bind-passwd PASSWORD \
--bind-method SIMPLE RW2_to_RO3

完成这些步骤后,可以使用 RW1 或 RW2 在 RO3 上执行数据库初始化。以下示例从 RW2 初始化 RO3:

> sudo dsconf INSTANCE_NAME repl-agmt init
--suffix dc=EXAMPLE,dc=COM RW2_to_RO3

5.11.6 监控和健康检查

dsconf 命令包括一个监控选项。您可以直接在复本上或者从其他主机检查每个复本的状态。以下示例命令在 RW1 上运行,用于检查两个远程复本的状态,然后检查 RW1 自身的状态:

> sudo dsconf -D "cn=Directory Manager" ldap://RW2 replication monitor
> sudo dsconf -D "cn=Directory Manager" ldap://RO3 replication monitor
> sudo dsconf -D "cn=Directory Manager" ldap://RW1 replication monitor

dsctl 命令有一个 healthcheck 选项。以下示例在本地 389 DS 实例上运行复制健康检查:

> sudo dsctl INSTANCE_NAME healthcheck --check replication

使用 -v(详细程度)选项查看健康检查所检查的内容:

> sudo dsctl -v INSTANCE_NAME healthcheck --check replication

不结合任何选项运行 dsctl INSTANCE_NAME healthcheck,以执行一般性的健康检查。

运行以下命令查看健康检查执行的检查列表:

> sudo dsctl INSTANCE_NAME healthcheck --list-checks
config:hr_timestamp
config:passwordscheme
backends:userroot:cl_trimming
backends:userroot:mappingtree
backends:userroot:search
backends:userroot:virt_attrs
encryption:check_tls_version
fschecks:file_perms
[...]

可以运行一项或多项独立检查:

> sudo dsctl INSTANCE_NAME healthcheck \
--check monitor-disk-space:disk_space tls:certificate_expiration

5.11.7 创建备份

启用复制后,需要调整 389 Directory Server 备份策略(请参见第 5.5 节 “备份和恢复 389 Directory Server”了解如何创建备份)。如果使用 db2ldif,则必须添加 --replication 标志,以确保备份复制元数据。应备份拓扑中的所有服务器。从备份恢复时,请先恢复拓扑的单个节点,然后将所有其他节点重新初始化为新实例。

5.11.8 暂停和继续复制

可以在维护时段暂停复制,或者在所需的任何时间停止复制。拓扑的节点最多只能在不超过更改日志限制的最大天数内保持脱机(请参见第 5.11.9 节 “ 更改日志 max-age”)。

使用 repl-agmt 命令暂停复制。以下示例在 RW2 上运行:

> sudo dsconf INSTANCE_NAME repl-agmt disable \
--suffix dc=EXAMPLE,dc=COM RW2_to_RW1

以下示例重新启用复制:

> sudo dsconf INSTANCE_NAME repl-agmt enable \
--suffix dc=EXAMPLE,dc=COM RW2_to_RW1

5.11.9 更改日志 max-age

复本可以在更改日志 max-age 选项定义的最大时长内保持脱机。max-age 定义更改日志中任何项的最长期限。系统会自动去除超过 max-age 值的任何项目。

复本恢复联机后,将与其他复本同步。如果脱机时间超过 max-age 值,则复本需要重新初始化,并且会拒绝接受更改或拒绝向其他节点提供更改,因为这些更改可能不一致。以下示例将 max-age 设置为七天:

> sudo dsconf INSTANCE_NAME \
replication set-changelog --max-age 7d \
--suffix dc=EXAMPLE,dc=COM

5.11.10 去除复本

要去除复本,首先请屏蔽节点,以防止任何传入的更改或读取。然后,找到与要去除的节点建立了传入复制协议的所有服务器并将其去除。以下示例去除 RW2。首先禁用 RW1 上的出站复制协议:

> sudo dsconf INSTANCE_NAME repl-agmt delete \
--suffix dc=EXAMPLE,dc=COM RW1_to_RW2

在要去除的复本(在以下示例中为 RW2)上,去除所有出站协议:

> sudo dsconf INSTANCE_NAME repl-agmt delete \
--suffix dc=EXAMPLE,dc=COM RW2_to_RW1
> sudo dsconf INSTANCE_NAME repl-agmt delete \
--suffix dc=EXAMPLE,dc=COM RW2_to_RO3

停止 RW2 上的实例:

> sudo systemctl stop dirsrv@INSTANCE_NAME.service

然后运行 cleanallruv 命令以从拓扑中去除复本 ID。以下示例在 RW1 上运行:

> sudo dsconf INSTANCE_NAME repl-tasks cleanallruv \
--suffix dc=EXAMPLE,dc=COM --replica-id 2
> sudo dsconf INSTANCE_NAME repl-tasks list-cleanruv-tasks

5.11.11 389 Directory Server 复制的限制

使用 389 Directory Server 时存在以下复制限制:

  • 最多 8 个读写节点

  • 最多 20 个复制中心

  • 最多 100 个只读服务器

  • 最多 1 个 Winsync Active Directory 使用者作为读写节点成员

5.12 与 Microsoft Active Directory 同步

389 Directory Server 支持同步 Microsoft Active Directory 中的某些用户和组内容,使 Linux 客户端能够使用 389 DS 获取其身份信息,而无需像一般情况下那样完成域加入过程。这也使得 389 DS 能够扩展自身的其他功能,并使用这些功能来处理从 Active Directory 同步的数据。

5.12.1 规划同步拓扑

由于同步的工作方式,此过程只涉及一个 389 Directory Server 和 Active Directory 服务器。Active Directory 服务器必须是完整的域控制器,而不是只读域控制器 (RODC)。在已同步的 DC 上不需要全局目录,因为 389 DS 仅复制域中单个林的内容。

必须首先选择数据流的方向。有三个选项:从 AD 流向 389 DS、从 389 DS 流向 AD,或双向。

注意
注意:不同步口令

无法在 389 DS 与 Active Directory 之间同步口令。这种情况将来可能会有改变,到时会支持从 Active Directory 到 389 DS 的口令流。

您的拓扑如下图所示。389 Directory Server 和 Active Directory 拓扑可能不同,但最重要的因素是 389 DS 与 Active Directory 之间只存在单个连接。请务必在 389 DS 和 AD 的灾难恢复与备份计划中考虑到这一点,以确保仅正确恢复这些拓扑之间的单个复制连接。

┌────────┐     ┌────────┐         ┌────────┐     ┌────────┐
│        │     │        │         │        │     │        │
│ 389-ds │◀───▶│ 389-ds │◀ ─ ─ ─ ▶│   AD   │◀───▶│   AD   │
│        │     │        │         │        │     │        │
└────────┘     └────────┘         └────────┘     └────────┘
    ▲               ▲                  ▲             ▲
    │               │                  │             │
    ▼               ▼                  ▼             ▼
┌────────┐     ┌────────┐         ┌────────┐     ┌────────┐
│        │     │        │         │        │     │        │
│ 389-ds │◀───▶│ 389-ds │         │   AD   │◀───▶│   AD   │
│        │     │        │         │        │     │        │
└────────┘     └────────┘         └────────┘     └────────┘

5.12.2 Active Directory 的先决条件

需要一个拥有“Replicating Directory Changes”权限的安全组。例如,假设您已创建一个名为 Directory Server Sync 的组,可以按照 How to grant the 'Replicating Directory Changes' permission for the Microsoft Metadirectory Services ADMA service account (https://docs.microsoft.com/en-US/troubleshoot/windows-server/windows-security/grant-replicating-directory-changes-permission-adma-service) 中的步骤设置此权限。

警告
警告:需要强安全性

应该将此组的成员安全性视为与域管理员的安全性同等重要。此组的成员能够从 Active Directory 环境中读取敏感内容,因此您应该为这些帐户使用随机生成的强服务帐户口令,并仔细审计此组的成员资格。

还应该创建一个服务帐户作为此组的成员。

您的 Active Directory 环境必须为 LDAPS 配置证书,以确保 389 DS 与 AD 之间的身份验证是安全的。无法将身份验证和通用安全服务 API/Kerberos (GSSAPI/KRB) 结合使用。

5.12.3 389 Directory Server 的先决条件

必须事先使用组织单元 (OU) 为 389 Directory Server 配置一个后端数据库,以便将项同步到其中。

必须为 389 Directory Server 配置一个复本 ID,使该服务器类似于一个读写复本。(有关设置复制的细节,请参见第 5.11 节 “设置复制”)。

5.12.4 创建从 Active Directory 到 389 Directory Server 的复制协议

以下示例命令在 389 Directory Server 上运行,它将创建从 Active Directory 到 389 Directory Server 的复制协议:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt create --suffix dc=example,dc=com \
  --host AD-HOSTNAME --port 636 --conn-protocol LDAPS \
  --bind-dn "cn=SERVICE-ACCOUNT,cn=USERS,dc=AD,dc=EXAMPLE,dc=COM" \
  --bind-passwd "PASSWORD" --win-subtree "cn=USERS,dc=AD,dc=EXAMPLE,dc=COM" \
  --ds-subtree ou=AD,dc=EXAMPLE,dc=COM --one-way-sync fromWindows \
  --sync-users=on --sync-groups=on --move-action delete \
  --win-domain AD-DOMAIN adsync_agreement

创建该协议后,必须执行初始重新同步:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt init --suffix dc=example,dc=com adsync_agreement

使用以下命令检查初始化状态:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt init-status --suffix dc=example,dc=com adsync_agreement
注意
注意:某些项不会同步

在某些情况下,即使初始化状态报告为成功,某个项也可能不会同步。检查 /var/log/dirsrv/slapd-INSTANCE-NAME/errors 中的 389 DS 日志文件。

使用以下命令检查协议状态:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt status --suffix dc=example,dc=com adsync_agreement

对 Active Directory 或 389 Directory Server 拓扑执行维护时,可以使用以下命令来暂停协议:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt disable --suffix dc=example,dc=com adsync_agreement

使用以下命令恢复协议:

> sudo dsconf INSTANCE-NAME repl-winsync-agmt enable --suffix dc=example,dc=com adsync_agreement

5.13 更多信息

有关 389 Directory Server 的详细信息,请参见: