32.5.轻型目录访问协议(LDAP)

轻量目录访问协议(LDAP)是一种应用层协议,用于访问、修改和验证对象,使用分布式目录信息服务。将其视为存储多个层次的分层、同质信息的电话簿或记录簿。它在 Active Directory 和 OpenLDAP 网络中使用,并能让用户通过单个账户访问多个内部信息级别。例如,电子邮件验证、提取员工联系信息和内部网站验证可能都会使用 LDAP 服务器记录库中的单个用户账户。

本节为在 FreeBSD 系统上配置 LDAP 服务器提供快速入门指南。它假定管理员已经有了包括要存储的信息类型、该信息将用于什么、哪些用户应该访问该信息以及如何保护此信息免受未经授权访问的设计计划。

32.5.1. LDAP 术语和结构

在开始配置之前,应了解 LDAP 使用的几个术语。所有目录条目由一组属性组成。每个属性集包含一个称为 Distinguished Name(DN)的唯一标识符,通常由其他几个属性(如常见或相对唯一名称(RDN))构建而成。类似于目录具有绝对路径和相对路径,将 DN 视为绝对路径,将 RDN 视为相对路径。

LDAP 示例条目如下。此示例搜索指定用户账户( uid )、组织单元( ou )和组织( o )的条目:

% ldapsearch -xb "uid=trhodes,ou=users,o=example.com"
# extended LDIF
#
# LDAPv3
# base <uid=trhodes,ou=users,o=example.com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# trhodes, users, example.com
dn: uid=trhodes,ou=users,o=example.com
mail: trhodes@example.com
cn: Tom Rhodes
uid: trhodes
telephoneNumber: (123) 456-7890

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

此示例条目显示 dn 、 mail 、 cn 、 uid 和 telephoneNumber 属性的值。cn 属性是 RDN。

有关 LDAP 及其术语的更多信息,请访问 http://www.openldap.org/doc/admin24/intro.html.

配置 LDAP 服务器

FreeBSD 不提供内置的 LDAP 服务器。通过安装 net/openldap-server 包或port来开始配置:

# pkg install openldap-server

在包中启用了大量默认选项。通过运行 pkg info openldap-server 来查看它们。如果它们不够用(例如需要 SQL 支持),请考虑使用适当的框架重新编译port。

安装将创建目录/var/db/openldap-data 以保存数据。必须创建用于存储证书的目录:

# mkdir /usr/local/etc/openldap/private

下一个阶段是配置证书授权中心。必须从/usr/local/etc/openldap/private 目录执行以下命令。这很重要,因为文件权限需要是严格的,并且用户不应该访问这些文件。关于证书及其参数的更详细信息可在 OpenSSL 中找到。要创建证书授权中心,请使用此命令并按照提示操作:

# openssl req -days 365 -nodes -new -x509 -keyout ca.key -out ../ca.crt

提示的条目可能是通用的,除了 Common Name。此条目必须不同于系统主机名。如果这将是自签名的证书,请使用 CA 前缀主机名用于证书授权中心。

下一个任务是创建证书签名请求和私钥。输入此命令并按照提示操作:

# openssl req -days 365 -nodes -new -keyout server.key -out server.csr

在证书生成过程中,请确保正确设置 Common Name 属性。证书签名请求必须由证书颁发机构签名,才能用作有效证书的一部分:

# openssl x509 -req -days 365 -in server.csr -out ../server.crt -CA ../ca.crt -CAkey ca.key -CAcreateserial

证书生成过程的最后一部分是生成和签名客户端证书:

# openssl req -days 365 -nodes -new -keyout client.key -out client.csr
# openssl x509 -req -days 3650 -in client.csr -out ../client.crt -CA ../ca.crt -CAkey ca.key

记得在提示时使用相同的 Common Name 属性。完成后,请确保通过下面的命令生成了总共八(8)个新文件。

运行 OpenLDAP 服务器的守护进程是 slapd。它的配置是通过 slapd.ldif 完成的:旧的 slapd.conf 已经被 OpenLDAP 弃用。

slapd.ldif 的配置示例可在/usr/local/etc/openldap/slapd.ldif.sample 中找到。选项在 slapd-config(5)中有文档记录。slapd.ldif 的每个部分,就像所有其他 LDAP 属性集一样,通过 DN 唯一标识。确保在 dn: 语句和所需部分的末尾之间没有空行。在下面的示例中,将使用 TLS 来实现安全通道。第一个部分代表全局配置:

#
# See slapd-config(5) for details on configuration options.
# This file should NOT be world readable.
#
dn: cn=config
objectClass: olcGlobal
cn: config
#
#
# Define global ACLs to disable default read access.
#
olcArgsFile: /var/run/openldap/slapd.args
olcPidFile: /var/run/openldap/slapd.pid
olcTLSCertificateFile: /usr/local/etc/openldap/server.crt
olcTLSCertificateKeyFile: /usr/local/etc/openldap/private/server.key
olcTLSCACertificateFile: /usr/local/etc/openldap/ca.crt
#olcTLSCipherSuite: HIGH
olcTLSProtocolMin: 3.1
olcTLSVerifyClient: never

证书颁发机构、服务器证书和服务器私钥文件必须在这里指定。建议让客户端选择安全密码,并省略选项 olcTLSCipherSuite (与除 openssl 之外的 TLS 客户端不兼容)。选项 olcTLSProtocolMin 允许服务器要求最低安全级别:建议。虽然服务器的验证是强制性的,但客户端的验证不是必需的: olcTLSVerifyClient: never。

第二部分是关于后端模块的,可以配置如下:

#
# Load dynamic backend modules:
#
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulepath:	/usr/local/libexec/openldap
olcModuleload:	back_mdb.la
#olcModuleload:	back_bdb.la
#olcModuleload:	back_hdb.la
#olcModuleload:	back_ldap.la
#olcModuleload:	back_passwd.la
#olcModuleload:	back_shell.la

第三部分专门用于加载必需的 ldif 模式,以供数据库使用:这些是必不可少的。

dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema

include: file:///usr/local/etc/openldap/schema/core.ldif
include: file:///usr/local/etc/openldap/schema/cosine.ldif
include: file:///usr/local/etc/openldap/schema/inetorgperson.ldif
include: file:///usr/local/etc/openldap/schema/nis.ldif

接下来是前端配置部分:

# Frontend settings
#
dn: olcDatabase={-1}frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: {-1}frontend
olcAccess: to * by * read
#
# Sample global access control policy:
#	Root DSE: allow anyone to read it
#	Subschema (sub)entry DSE: allow anyone to read it
#	Other DSEs:
#		Allow self write access
#		Allow authenticated users read access
#		Allow anonymous users to authenticate
#
#olcAccess: to dn.base="" by * read
#olcAccess: to dn.base="cn=Subschema" by * read
#olcAccess: to *
#	by self write
#	by users read
#	by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn.  (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
#
olcPasswordHash: {SSHA}
# {SSHA} is already the default for olcPasswordHash

另一部分专门用于配置后端,之后访问 OpenLDAP 服务器配置的唯一方式是作为全局超级用户。

dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: to * by * none
olcRootPW: {SSHA}iae+lrQZILpiUdf16Z9KmDmSwT77Dj4U

默认管理员用户名是 cn=config。在shell中键入 slappasswd,选择一个密码并在 olcRootPW 中使用其哈希值。如果现在没有指定此选项,在导入 slapd.ldif 之前,以后将没有人能够修改全局配置部分。

最后一部分是关于数据库后端的:

#######################################################################
# LMDB database definitions
#######################################################################
#
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcSuffix: dc=domain,dc=example
olcRootDN: cn=mdbadmin,dc=domain,dc=example
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd-config(5) for details.
# Use of strong authentication encouraged.
olcRootPW: {SSHA}X2wHvIWDk6G76CQyCMS1vDCvtICWgn0+
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
olcDbDirectory:	/var/db/openldap-data
# Indices to maintain
olcDbIndex: objectClass eq

此数据库托管 LDAP 目录的实际内容。除 mdb 之外,还有其他类型可用。其超级用户(不要与全局用户混淆)在此处配置: olcRootDN 中的(可能是自定义的)用户名和 olcRootPW 中的密码哈希值;如以前一样,可以使用 slappasswd。

此存储库包含四个 slapd.ldif 示例。要将现有的 slapd.conf 转换为 slapd.ldif,请参考本页(请注意,这可能会引入一些无用选项)。

当配置完成后,slapd.ldif 必须放在一个空目录中。建议将其创建为:

# mkdir /usr/local/etc/openldap/slapd.d/

导入配置数据库:

# /usr/local/sbin/slapadd -n0 -F /usr/local/etc/openldap/slapd.d/ -l /usr/local/etc/openldap/slapd.ldif

启动 slapd 守护程序:

# /usr/local/libexec/slapd -F /usr/local/etc/openldap/slapd.d/

选项 -d 可用于调试,在 slapd(8)中指定。要验证服务器正在运行和工作:

# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#

#
dn:
namingContexts: dc=domain,dc=example

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

服务器仍须受信任。如果以前从未执行过此操作,请按照以下说明操作。安装 OpenSSL 软件包或 port:

# pkg install openssl

从存储 ca.crt 的目录中(例如,在此示例中为 /usr/local/etc/openldap)运行:

# c_rehash .

CA 证书和服务器证书现在在各自的角色中被正确识别。要验证这一点,请从 server.crt 目录运行以下命令:

# openssl verify -verbose -CApath . server.crt

如果 slapd 正在运行,请重启它。如在/usr/local/etc/rc.d/slapd 中所述,要正确地在启动时运行 slapd,必须将以下行添加到/etc/rc.conf 中:

slapd_enable="YES"
slapd_flags='-h "ldapi://%2fvar%2frun%2fopenldap%2fldapi/
ldap://0.0.0.0/"'
slapd_sockets="/var/run/openldap/ldapi"
slapd_cn_config="YES"

slapd 在启动时不提供调试。为此,请检查/var/log/debug.log、dmesg -a 和/var/log/messages。

以下示例将组 team 和用户 john 添加到仍为空的 domain.example LDAP 数据库中。首先,创建文件 domain.ldif:

# cat domain.ldif
dn: dc=domain,dc=example
objectClass: dcObject
objectClass: organization
o: domain.example
dc: domain

dn: ou=groups,dc=domain,dc=example
objectClass: top
objectClass: organizationalunit
ou: groups

dn: ou=users,dc=domain,dc=example
objectClass: top
objectClass: organizationalunit
ou: users

dn: cn=team,ou=groups,dc=domain,dc=example
objectClass: top
objectClass: posixGroup
cn: team
gidNumber: 10001

dn: uid=john,ou=users,dc=domain,dc=example
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: John McUser
uid: john
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/john/
loginShell: /usr/bin/bash
userPassword: secret

有关更多详细信息,请参阅 OpenLDAP 文档。使用 slappasswd 将纯文本密码 secret 替换为 userPassword 中的哈希值。指定为 loginShell 的路径必须存在于允许 john 登录的所有系统中。最后,使用 mdb 管理员修改数据库:

# ldapadd -W -D "cn=mdbadmin,dc=domain,dc=example" -f domain.ldif

对全局配置部分的修改只能由全局超级用户执行。例如,假设最初指定了选项 olcTLSCipherSuite: HIGH:MEDIUM:SSLv3,现在必须将其删除。首先,创建包含以下内容的文件:

# cat global_mod
dn: cn=config
changetype: modify
delete: olcTLSCipherSuite

然后,应用修改:

# ldapmodify -f global_mod -x -D "cn=config" -W

当被询问时,请提供在配置后端部分选择的密码。不需要用户名:这里,cn=config 代表要修改的数据库部分的 DN。或者,使用 ldapmodify 删除数据库的单行,使用 ldapdelete 删除整个条目。

如果出现问题,或者全局超级用户无法访问配置后端,可以删除并重新编写整个配置:

# rm -rf /usr/local/etc/openldap/slapd.d/

slapd.ldif 然后可以进行编辑并重新导入。请在没有其他解决方案可用时才按照此过程操作。

这仅是服务器的配置。同一台机器也可以托管 LDAP 客户端,并具有自己独立的配置。

最后更新于

FreeBSD 中文社区 2024