Product SiteDocumentation Site

11.7. LDAP 目录

OpenLDAP 是 LDAP 协议的应用;换句话说,它是设计来存储目录的特定功能数据库。在最通常的使用情况下,使用 LDAP 服务器允许集中管理用户账户和相关的权限。而且,LDAP 数据库复制容易,这允许设置多个同步的 LDAP 服务器。当网络和用户基础迅速增长时,负载然后会在几台服务器之间平衡。
LDAP 数据是结构化的并且分层级的。结构由“schemas(架构)”来确定,它使用了所有可能的属性列表,来描述数据库可以存储的对象的种类。用于指示数据库中特定对象的语法基于这个结构,它解释了其复杂性。

11.7.1. 安装

slapd 软件包包含 OpenLDAP 服务器。ldap-utils 软件包包括了与 LDAP 服务器交互的命令行工具。
安装 slapd 通常只询问管理员的密码,并且产生的数据库可能并不适合您的需求。幸运的是,简单的 dpkg-reconfigure slapd 将让您更具体地重新配置 LDAP 数据库:
  • 省略 OpenLDAP 服务器的配置?不,当然不,我们想要配置这个服务。
  • DNS 域名:“falcot.com”。
  • 组织名称:“Falcot Corp”。
  • 管理密码需要键入。
  • 数据库后端要使用:“MDB”。
  • 当清除 slapd 时想要删除数据库吗?不,没有必要在犯错误的情况下冒丢失数据库的风险。
  • 移动旧的数据库吗?只有在数据库已经存在而尝试进行配置的情况下才询问这个问题。如果真的想从干净的数据库重新开始时才能回答“是”,例如,如果刚好在初始安装后运行 dpkg-reconfigure slapd 的情况下。
现在配置了最小数据库,如后面的查询所说明的:
$ ldapsearch -x -b dc=falcot,dc=com
# extended LDIF
#
# LDAPv3
# base <dc=falcot,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# falcot.com
dn: dc=falcot,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Falcot Corp
dc: falcot

# admin, falcot.com
dn: cn=admin,dc=falcot,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
请求返回两个对象:组织自身和管理用户。

11.7.2. 填入目录

由于空数据库不特别有用,我们将所有现有目录注入其中;这包括用户、用户组、服务和主机数据库。
migrationtools 软件包提供一组脚本,专门用于从标准 Unix 目录中提取数据(/etc/passwd/etc/group/etc/services/etc/hosts 以及等等诸如此类),转换这个数据,并将其注入 LDAP 数据库中。
一旦安装了软件包,就必须编辑 /etc/migrationtools/migrate_common.ph;需要启用 IGNORE_UID_BELOWIGNORE_GID_BELOW 选项(将其取消注释就足够了),并且需要更新 DEFAULT_MAIL_DOMAIN/DEFAULT_BASE
真正的迁移操作由 migrate_all_online.sh 命令来处理,如下:
# cd /usr/share/migrationtools
# PERL5LIB="${PERL5LIB}:/etc/migrationtools" LDAPADD="/usr/bin/ldapadd -c" ETC_ALIASES=/dev/null ./migrate_all_online.sh
migrate_all_online.sh 询问一些关于数据迁移到 LDAP 数据库的问题。表 11.1 概括了 Falcot 公司的使用案例中给出回答。

表 11.1. 对 migrate_all_online.sh 脚本询问的问题的回答

问题回答
X.500 命名文本dc=falcot,dc=com
LDAP 服务器主机名localhost
管理者 DNcn=admin,dc=falcot,dc=com
绑定证明管理员密码
创建 DUAConfigProfile
You might notice that we extend the PERL5LIB variable. This is due to Debian bug report #982666.
As you might have also noticed, we deliberately ignore migration of the /etc/aliases file, since the standard schema as provided by Debian does not include the structures that this script uses to describe email aliases. Should we want to integrate this data into the directory, the /etc/ldap/schema/misc.schema file should be added to the standard schema.
还要注意 -c 选项在 ldapadd 命令中的使用;这个选项需要在错误的情况下不将处理停止下来。使用这个选项的使用是需要的,因为 /etc/services 的转换通常产生一些可以被安全地忽略的错误。

11.7.3. 使用 LDAP 管理账户

现在 LDAP 数据库包含了一些有用的信息,是时候使用这些数据了。这一节聚焦于如何配置 Linux 系统,从而各个系统目录可以使用 LDAP 数据库。

11.7.3.1. 配置 NSS

The NSS system (Name Service Switch, see sidebar 进一步 NSS 与系统数据库) is a modular system designed to define or fetch information for system directories. Using LDAP as a source of data for NSS requires installing the libnss-ldapd package.
The /etc/nsswitch.conf file then needs to be modified, so as to configure NSS to use the freshly-installed ldap module.

例 11.23. The /etc/nsswitch.conf file

# /etc/nsswitch.conf
#
# An example file that could be copied over to /etc/nsswitch.conf; it
# uses LDAP conjunction with files.
#
# "hosts:" and "services:" in this file are used only if the
# /etc/netconfig file has a "-" for nametoaddr_libs of "inet" transports.

# the following lines obviate the "+" entry in /etc/passwd and /etc/group.
passwd:         files ldap
shadow:         files ldap
group:          files ldap

# consult DNS first, we will need it to resolve the LDAP host. (If we
# can't resolve it, we're in infinite recursion, because libldap calls
# gethostbyname(). Careful!)
hosts:          dns ldap

# LDAP is nominally authoritative for the following maps.
services:   ldap [NOTFOUND=return] files
networks:   ldap [NOTFOUND=return] files
protocols:  ldap [NOTFOUND=return] files
rpc:        ldap [NOTFOUND=return] files
ethers:     ldap [NOTFOUND=return] files

# no support for netmasks, bootparams, publickey yet.
netmasks:   files
bootparams: files
publickey:  files
automount:  files

# I'm pretty sure nsswitch.conf is consulted directly by sendmail,
# here, so we can't do much here. Instead, use bbense's LDAP
# rules ofr sendmail.
aliases:    files
sendmailvars:   files

# Note: there is no support for netgroups on Solaris (yet)
netgroup:   ldap [NOTFOUND=return] files
ldap 模块通常插在其它之前,这样会被首先询问。显著的例外是 hosts 服务,因为联系 LDAP 服务器需要首先咨询 DNS (来解析 ldap.falcot.com)。没有这个例外的话,主机名查询将试图询问 LDAP 服务器;这会触发对 LDAP 服务器的名称解析,于是进入死循环。
如果 LDAP 服务器被认为是权威的(并且不理会 files 模块使用的本地文件),那么服务可以使用后面的语法来配置:
服务: ldap [NOTFOUND=return] files.
如果请求的入口在 LDAP 数据库中不存在,那么即使资源真实存在于一个本地文件中,查询也会返回“不存在”的回复;这些本地文件只当 LDAP 服务关闭时才会使用。

11.7.3.2. 配置 PAM

本节描述了 PAM 配置(请参见边栏 幕后/etc/environment/etc/default/locale),它允许应用针对 LDAP 数据库来执行所需要的授权。
The LDAP module for PAM is provided by the libpam-ldapd package. Installing this package asks a few questions very similar to those in libnss-ldapd; some configuration parameters (such as the URI for the LDAP server) are even actually shared with the libnss-ldapd package.
Installing libpam-ldapd automatically adapts the default PAM configuration defined in the /etc/pam.d/common-auth, /etc/pam.d/common-password and /etc/pam.d/common-account files. This mechanism uses the dedicated pam-auth-update tool (provided by the libpam-runtime package). This tool can also be run by the administrator should they wish to enable or disable PAM modules.

11.7.3.3. 保护 LDAP 数据交换

LDAP 协议默认在网络上明文传输;这包括(加密的)密码。由于加密的密码可以从网络上提取,它们对字典类型的攻击会是脆弱的。这可以通过使用另外的加密层来避免;启用这层是本节的主题。
11.7.3.3.1. 配置服务器
第一步是为 LDAP 服务器创建密钥对(包括公钥和私钥)。Falcot 公司的管理员重复使用 easy-rsa 来生成它(请参见 第 10.2.2 节 “公钥基础设施:easy-rsa)。运行 ./easyrsa build-server-full ldap.falcot.com nopass 会询问有关“通用名称”。对问题的回答必须是 LDAP 服务器完全合格的主机名;在我们的例子中是 ldap.falcot.com
这个命令在 pki/issued/ldap.falcot.com.crt 文件中创建了证书;相应的私钥存储在 pki/private/ldap.falcot.com.key 中。
现在这些密钥必须安装到其标准位置上,并且我们必须确定私有文件可以被openldap身份下运行的 LDAP 服务器读取:
# adduser openldap ssl-cert
Adding user `openldap' to group `ssl-cert' ...
Adding user openldap to group ssl-cert
Done.
# mv pki/private/ldap.falcot.com.key /etc/ssl/private/ldap.falcot.com.key
# chown root.ssl-cert /etc/ssl/private/ldap.falcot.com.key
# chmod 0640 /etc/ssl/private/ldap.falcot.com.key
# mv pki/issued/ldap.falcot.com.crt /etc/ssl/certs/ldap.falcot.com.pem
# chown root.root /etc/ssl/certs/ldap.falcot.com.pem
# chmod 0644 /etc/ssl/certs/ldap.falcot.com.pem
还需要告知 slapd 守护进程使用这些密钥来加密。LDAP 服务器的配置被动态地管理:可以在 cn=config 对象层次结构上通过正常的 LDAP 操做来更新配置;并且服务器实时更新 /etc/ldap/slapd.d 而使配置持续。这样 ldapmodify 就是更新配置的合适工具了:

例 11.24. 配置 slapd 来加密

# cat >ssl.ldif <<END
dn: cn=config
changetype: modify
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap.falcot.com.key
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap.falcot.com.pem
END
# ldapmodify -Y EXTERNAL -H ldapi:/// -f ssl.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
# systemctl restart slapd.service
# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config -s base | grep TLS
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
olcTLSCertificateFile: /etc/ssl/certs/ldap.falcot.com.pem
olcTLSCertificateKeyFile: /etc/ssl/certs/ldap.falcot.com.key
启用加密的最后一步包括更改 /etc/default/slapd 文件中的 SLAPD_SERVICES 变量。我们将同时安全地运行并禁止不安全 LDAP。

例 11.25. /etc/default/slapd 文件

# Default location of the slapd.conf file or slapd.d cn=config directory. If
# empty, use the compiled-in default (/etc/ldap/slapd.d with a fallback to
# /etc/ldap/slapd.conf).
SLAPD_CONF=

# System account to run the slapd server under. If empty the server
# will run as root.
SLAPD_USER="openldap"

# System group to run the slapd server under. If empty the server will
# run in the primary group of its user.
SLAPD_GROUP="openldap"

# Path to the pid file of the slapd server. If not set the init.d script
# will try to figure it out from $SLAPD_CONF (/etc/ldap/slapd.d by
# default)
SLAPD_PIDFILE=

# slapd normally serves ldap only on all TCP-ports 389. slapd can also
# service requests on TCP-port 636 (ldaps) and requests via unix
# sockets.
# Example usage:
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
SLAPD_SERVICES="ldaps:/// ldapi:///"

# If SLAPD_NO_START is set, the init script will not start or restart
# slapd (but stop will still work).  Uncomment this if you are
# starting slapd via some other means or if you don't want slapd normally
# started at boot.
#SLAPD_NO_START=1

# If SLAPD_SENTINEL_FILE is set to path to a file and that file exists,
# the init script will not start or restart slapd (but stop will still
# work).  Use this for temporarily disabling startup of slapd (when doing
# maintenance, for example, or through a configuration management system)
# when you don't want to edit a configuration file.
SLAPD_SENTINEL_FILE=/etc/ldap/noslapd

# For Kerberos authentication (via SASL), slapd by default uses the system
# keytab file (/etc/krb5.keytab).  To use a different keytab file,
# uncomment this line and change the path.
#export KRB5_KTNAME=/etc/krb5.keytab

# Additional options to pass to slapd
SLAPD_OPTIONS=""
11.7.3.3.2. 配置客户端
On the client side, the configuration for the libpam-ldapd and libnss-ldapd modules needs to be modified to use an ldaps:// URI.
LDAP clients also need to be able to authenticate the server. In an X.509 public key infrastructure, public certificates are signed by the key of a certificate authority (CA). With easy-rsa, the Falcot administrators have created their own CA and they now need to configure the system to trust the signatures of Falcot's CA. This can be done by putting the CA certificate in /usr/local/share/ca-certificates and running update-ca-certificates.
# cp pki/ca.crt /usr/local/share/ca-certificates/falcot.crt
# update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...

Adding debian:falcot.pem
done.
done.
最后但不是最重要的,各种命令行工具使用的默认 LDAP URI 和默认基础 DN可以在 /etc/ldap/ldap.conf 中修改。这会节省一些输入工作。

例 11.26. /etc/ldap/ldap.conf 文件

#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE   dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-provider.example.com:666

#SIZELIMIT      12
#TIMELIMIT      15
#DEREF          never

# TLS certificates (needed for GnuTLS)
TLS_CACERT      /etc/ssl/certs/ca-certificates.crt