第21章 其他文件系统
附录 D. OpenPGP 密钥
30.5.轻型目录访问协议(LDAP)
轻型目录访问协议 (LDAP) 是一种应用层协议,用于使用分布式目录信息服务访问、修改和验证对象。可以把它想象成一本电话或唱片簿,它存储了几个层次的分层、同质信息。它用于 Active Directory 和 OpenLDAP 网络,允许用户使用单个帐户访问多个级别的内部信息。例如,电子邮件身份验证、提取员工联系信息和内部网站身份验证都可能使用 LDAP 服务器记录库中的单个用户帐户。
本节提供在 FreeBSD 系统上配置 LDAP 服务器的快速入门指南。它假定管理员已经有一个设计计划,其中包括要存储的信息类型、该信息将用于什么目的、哪些用户应有权访问该信息,以及如何防止未经授权的访问。

30.5.1. LDAP 术语和结构

LDAP 使用几个术语,在开始配置之前应了解这些术语。所有目录条目都由一组 属性 组成。这些属性集中的每一个都包含一个称为 可分辨名称 (DN) 的唯一标识符,该标识符通常由其他几个属性(如公用或 相对可分辨名称 (RDN))构建。与目录具有绝对路径和相对路径的方式类似,将 DN 视为绝对路径,将 RDN 视为相对路径。
示例 LDAP 条目如下所示。本示例搜索指定用户帐户 (uid)、组织单位 (ou) 和组织 (o) 的条目:
1
% ldapsearch -xb "uid=trhodes,ou=users,o=example.com"
2
# extended LDIF
3
#
4
# LDAPv3
5
# base <uid=trhodes,ou=users,o=example.com> with scope subtree
6
# filter: (objectclass=*)
7
# requesting: ALL
8
#
9
10
# trhodes, users, example.com
11
dn: uid=trhodes,ou=users,o=example.com
13
cn: Tom Rhodes
14
uid: trhodes
15
telephoneNumber: (123) 456-7890
16
17
# search result
18
search: 2
19
result: 0 Success
20
21
# numResponses: 2
22
# numEntries: 1
Copied!
此示例条目显示 dnmailcnuidtelephoneNumber 属性的值。cn 属性是 RDN。
有关 LDAP 及其术语的更多信息,请参阅 http://www.openldap.org/doc/admin24/intro.html。

30.5.2. 配置 LDAP 服务器

FreeBSD 不提供内置的 LDAP 服务器。通过安装 net/openldap 服务器软件包或 port 开始配置:
1
# pkg install openldap-server
Copied!
package 中启用了大量默认选项。通过运行 pkg info openldap-server 来查看它们。如果它们还不够(例如,如果需要 SQL 支持),请考虑使用适当的 framework 重新编译 port。
安装将创建目录 /var/db/openldap-data 来保存数据。必须创建用于存储证书的目录:
1
# mkdir /usr/local/etc/openldap/private
Copied!
下一阶段是配置证书颁发机构。以下命令必须从 /usr/local/etc/openldap/private 执行。这一点很重要,因为文件权限需要受到限制,并且用户不应有权访问这些文件。有关证书及其参数的更多详细信息,请参阅 OpenSSL。要创建证书颁发机构,请从以下命令开始,然后按照提示操作:
1
# openssl req -days 365 -nodes -new -x509 -keyout ca.key -out ../ca.crt
Copied!
提示的条目可能是通用的,但 Common Name 条目必须与系统主机名 不同 。如果这是自签名证书,请在主机名前面加上“证书颁发机构”前缀 CA
下一个任务是创建证书签名请求和私钥。输入以下命令并按照提示操作:
1
# openssl req -days 365 -nodes -new -keyout server.key -out server.csr
Copied!
在证书生成过程中,请确保正确设置 Common Name 属性。证书签名请求必须使用证书颁发机构进行签名,才能用作有效证书:
1
# openssl x509 -req -days 365 -in server.csr -out ../server.crt -CA ../ca.crt -CAkey ca.key -CAcreateserial
Copied!
证书生成过程的最后一部分是生成客户端证书并对其进行签名:
1
# openssl req -days 365 -nodes -new -keyout client.key -out client.csr
2
# openssl x509 -req -days 3650 -in client.csr -out ../client.crt -CA ../ca.crt -CAkey ca.key
Copied!
请记住在出现提示时使用相同的 Common Name 属性。完成后,确保通过一连串命令总共生成了 8 个新文件。
运行 OpenLDAP 服务器的守护程序已 过期。它的配置是通过 slapd.ldif 执行的:旧的 slapd.conf 已被 OpenLDAP 弃用。
slapd.ldif配置示例可用,也可以在 /usr/local/etc/openldap/slapd.ldif.sample 中找到。选项记录在 slapd-config(5) 中。与所有其他 LDAP 属性集一样,slapd.ldif 的每个部分都通过 DN 进行唯一标识。请确保在语句和该部分的所需末尾之间不留任何空行。在以下示例中,TLS 将用于实现安全通道。第一部分是全局配置:
1
#
2
# See slapd-config(5) for details on configuration options.
3
# This file should NOT be world readable.
4
#
5
dn: cn=config
6
objectClass: olcGlobal
7
cn: config
8
#
9
#
10
# Define global ACLs to disable default read access.
11
#
12
olcArgsFile: /var/run/openldap/slapd.args
13
olcPidFile: /var/run/openldap/slapd.pid
14
olcTLSCertificateFile: /usr/local/etc/openldap/server.crt
15
olcTLSCertificateKeyFile: /usr/local/etc/openldap/private/server.key
16
olcTLSCACertificateFile: /usr/local/etc/openldap/ca.crt
17
#olcTLSCipherSuite: HIGH
18
olcTLSProtocolMin: 3.1
19
olcTLSVerifyClient: never
Copied!
必须在这里指定证书机构、服务器证书和服务器私钥文件。建议让客户选择安全密码,省略选项 olcTLSCipherSuite (与 openssl 以外的 TLS 客户不兼容)。选项olcTLSProtocolMin让服务器要求一个最低的安全级别:建议使用。虽然验证对服务器来说是强制性的,但对客户端来说却不是必需的:olcTLSVerifyClient:never
第二部分是关于后端模块的,可以按如下方式配置:
1
#
2
# Load dynamic backend modules:
3
#
4
dn: cn=module,cn=config
5
objectClass: olcModuleList
6
cn: module
7
olcModulepath: /usr/local/libexec/openldap
8
olcModuleload: back_mdb.la
9
#olcModuleload: back_bdb.la
10
#olcModuleload: back_hdb.la
11
#olcModuleload: back_ldap.la
12
#olcModuleload: back_passwd.la
13
#olcModuleload: back_shell.la
Copied!
第三部分专门用于加载数据库使用的所需 ldif 架构:它们是必不可少的。
1
dn: cn=schema,cn=config
2
objectClass: olcSchemaConfig
3
cn: schema
4
5
include: file:///usr/local/etc/openldap/schema/core.ldif
6
include: file:///usr/local/etc/openldap/schema/cosine.ldif
7
include: file:///usr/local/etc/openldap/schema/inetorgperson.ldif
8
include: file:///usr/local/etc/openldap/schema/nis.ldif
Copied!
接下来,前端配置部分:
1
# Frontend settings
2
#
3
dn: olcDatabase={-1}frontend,cn=config
4
objectClass: olcDatabaseConfig
5
objectClass: olcFrontendConfig
6
olcDatabase: {-1}frontend
7
olcAccess: to * by * read
8
#
9
# Sample global access control policy:
10
# Root DSE: allow anyone to read it
11
# Subschema (sub)entry DSE: allow anyone to read it
12
# Other DSEs:
13
# Allow self write access
14
# Allow authenticated users read access
15
# Allow anonymous users to authenticate
16
#
17
#olcAccess: to dn.base="" by * read
18
#olcAccess: to dn.base="cn=Subschema" by * read
19
#olcAccess: to *
20
# by self write
21
# by users read
22
# by anonymous auth
23
#
24
# if no access controls are present, the default policy
25
# allows anyone and everyone to read anything but restricts
26
# updates to rootdn. (e.g., "access to * by * read")
27
#
28
# rootdn can always read and write EVERYTHING!
29
#
30
olcPasswordHash: {SSHA}
31
# {SSHA} is already the default for olcPasswordHash
Copied!
另一部分专门介绍配置后端,以后访问 OpenLDAP 服务器配置的唯一方法是作为全局超级用户。
1
dn: olcDatabase={0}config,cn=config
2
objectClass: olcDatabaseConfig
3
olcDatabase: {0}config
4
olcAccess: to * by * none
5
olcRootPW: {SSHA}iae+lrQZILpiUdf16Z9KmDmSwT77Dj4U
Copied!
缺省管理员用户名为 cn=config。在 shell 中键入 slappasswd,选择一个密码并在 olcRootPW 中使用其哈希值。如果现在未指定此选项,则在导入 slapd.ldif 之前,以后任何人都无法修改全局配置部分。
最后一部分是关于数据库后端的:
1
#######################################################################
2
# LMDB database definitions
3
#######################################################################
4
#
5
dn: olcDatabase=mdb,cn=config
6
objectClass: olcDatabaseConfig
7
objectClass: olcMdbConfig
8
olcDatabase: mdb
9
olcDbMaxSize: 1073741824
10
olcSuffix: dc=domain,dc=example
11
olcRootDN: cn=mdbadmin,dc=domain,dc=example
12
# Cleartext passwords, especially for the rootdn, should
13
# be avoided. See slappasswd(8) and slapd-config(5) for details.
14
# Use of strong authentication encouraged.
15
olcRootPW: {SSHA}X2wHvIWDk6G76CQyCMS1vDCvtICWgn0+
16
# The database directory MUST exist prior to running slapd AND
17
# should only be accessible by the slapd and slap tools.
18
# Mode 700 recommended.
19
olcDbDirectory: /var/db/openldap-data
20
# Indices to maintain
21
olcDbIndex: objectClass eq
Copied!
这个数据库承载 LDAP 目录的实际内容。除了 mdb 之外,其他类型的数据库都可以使用。它的超级用户,不要和全局用户混淆,在这里配置: olcRootDN 中一个(可能是自定义的)用户名和 olcRootPW 中的密码散列;slappasswd 可以像以前一样使用。
存储库包含 slapd.ldif 的四个示例。要将现有的 slapd.conf 转换为 slapd.ldif,请参阅此页面(请注意,这可能会引入一些无用的选项)。
配置完成后,必须将 slapd.ldif 放在空目录中。建议将其创建为:
1
# mkdir /usr/local/etc/openldap/slapd.d/
Copied!
导入配置数据库:
1
# /usr/local/sbin/slapadd -n0 -F /usr/local/etc/openldap/slapd.d/ -l /usr/local/etc/openldap/slapd.ldif
Copied!
启动 slapd 守护程序:
1
# /usr/local/libexec/slapd -F /usr/local/etc/openldap/slapd.d/
Copied!
-d 选项可用于调试,如 slapd(8) 中所述。要验证服务器是否正在运行且工作正常,请执行以下操作:
1
# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
2
# extended LDIF
3
#
4
# LDAPv3
5
# base <> with scope baseObject
6
# filter: (objectclass=*)
7
# requesting: namingContexts
8
#
9
10
#
11
dn:
12
namingContexts: dc=domain,dc=example
13
14
# search result
15
search: 2
16
result: 0 Success
17
18
# numResponses: 2
19
# numEntries: 1
Copied!
服务器仍必须受信任。如果以前从未这样做过,请按照以下说明进行操作。安装 OpenSSL 软件包或 port:
1
# pkg install openssl
Copied!
从存储 ca.crt 的目录(在此示例中为 /usr/local/etc/openldap),运行:
1
# c_rehash .
Copied!
CA 和服务器证书现在都可以在各自的角色中正确识别。若要验证这一点,请从 server.crt 目录运行以下命令:
1
# openssl verify -verbose -CApath . server.crt
Copied!
如果 slapd 正在运行,请重新启动它。如 /usr/local/etc/rc.d/slapd 中所述,要在引导时正确运行 slapd,必须在 /etc/rc.conf 中添加以下行:
1
slapd_enable="YES"
2
slapd_flags='-h "ldapi://%2fvar%2frun%2fopenldap%2fldapi/
3
ldap://0.0.0.0/"'
4
slapd_sockets="/var/run/openldap/ldapi"
5
slapd_cn_config="YES"
Copied!
slapd 不提供启动时的调试。为此,请检查 /var/log/debug.logdmesg -a/var/log/messages
下面的例子将组 team 和用户 john 添加到 domain.example LDAP 数据库中,该数据库仍然是空的。首先,创建文件 domain.ldif
1
# cat domain.ldif
2
dn: dc=domain,dc=example
3
objectClass: dcObject
4
objectClass: organization
5
o: domain.example
6
dc: domain
7
8
dn: ou=groups,dc=domain,dc=example
9
objectClass: top
10
objectClass: organizationalunit
11
ou: groups
12
13
dn: ou=users,dc=domain,dc=example
14
objectClass: top
15
objectClass: organizationalunit
16
ou: users
17
18
dn: cn=team,ou=groups,dc=domain,dc=example
19
objectClass: top
20
objectClass: posixGroup
21
cn: team
22
gidNumber: 10001
23
24
dn: uid=john,ou=users,dc=domain,dc=example
25
objectClass: top
26
objectClass: account
27
objectClass: posixAccount
28
objectClass: shadowAccount
29
cn: John McUser
30
uid: john
31
uidNumber: 10001
32
gidNumber: 10001
33
homeDirectory: /home/john/
34
loginShell: /usr/bin/bash
35
userPassword: secret
Copied!
更多细节请参见 OpenLDAP 文档。使用 slappasswd 将纯文本密码secret 替换为 userPassword 中的哈希值。作为 loginShell 指定的路径必须存在于所有允许 john 登录的系统中。最后,使用 mdb 管理员来修改数据库。
1
# ldapadd -W -D "cn=mdbadmin,dc=domain,dc=example" -f domain.ldif
Copied!
对_全局配置_部分的修改只能由全局超级用户执行。例如,假定最初指定olcTLSCipherSuite: HIGH:MEDIUM:SSLv3 选项,现在必须将其删除。首先,创建一个包含以下内容的文件:
1
# cat global_mod
2
dn: cn=config
3
changetype: modify
4
delete: olcTLSCipherSuite
Copied!
然后,应用修改:
1
# ldapmodify -f global_mod -x -D "cn=config" -W
Copied!
当被要求时,提供在配置后台部分选择的密码。用户名不是必需的:在这里,cn=config 代表要修改的数据库部分的DN。另外,使用 ldapmodify 来删除数据库中的某一行,ldapdelete 来删除整个条目。
如果出现问题,或者全局超级用户无法访问配置后端,则可以删除并重新写入整个配置:
1
# rm -rf /usr/local/etc/openldap/slapd.d/
Copied!
然后可以编辑并再次导入 slapd.ldif。请仅在没有其他可用解决方案时才执行此过程。
这只是服务器的配置。同一台计算机还可以托管 LDAP 客户端,并具有自己单独的配置。