本文发布于Cylon的收藏册,转载请著名原文链接~

生产服务器硬件配置需求

ldap服务对系统环境的要求不高,一般在生产场景,ldap服务应该最少是两台,这样某一台物理服务器岩机才不会因单点问题影响生产业务故障,对于硬件要求,本质上openldap使用硬件资源并不大,网上有两个帖子提出了openldap的硬件需求:

  • 2003年openldap官网留言,我想安装一个 LDAP 服务器来验证邮件服务器的用户,目前有200个用户需要多少内存和CPU?[1]
    • 1GHZ PIII/512MB 足以
  • 运行于Ubuntu LXC 之上的openldap,用户150,000,sladp进程常驻内存为200-300MB,mdb数据库文件大小为377MB,10 并发平均响应时间为 9-11 毫秒 [13]

操作系统:Centos7/8 64bit。

操 作 系 统 其 它
CentOS-7.6 当前很稳定且免费的Linux版本。

网卡及IP资源

名 称 接 口 IP 用途
ldap主服务器01 eth0 10.0.0.17 外部管理IP,用于WAN数据转发。
eth1 10.0.0.17 备用管理IP,用于LAN内数据转发。
ldap从服务器02 eth0 10.0.0.8 管理IP,用于LAN数据转发。
eth1 10.0.0.18 外部管理IP,用于WAN数据转发。

Tips:内外网IP分配可采用最后8位相同的方式,这样使于管理。


openldap master服务安装

CentOS/Redhat 安装OpenLDAP组件

1
2
3
4
5
6
yum install -y \
	openldap \
	openldap-servers \
	openldap-clients \
	openldap-devel \
	compat-openldap

Ubuntu18.04/22.04/20.04

1
sudo apt -y install slapd ldap-utils

默认OpenLDAP服务所使用的端口为389,此端口采用明文传输数据,数据信息得不到保障。所以可以通过配置CA及结合TLS/SASL实现数据加密传输,所使用端口为636。

编译安装

1
2
3
4
5
6
yum install -y \
	libtool-ltdl \
	libtool-ltdl-devel \
	gcc \
	openssl \
	openssl-devel

Openldap依赖的相关软件:

openldap参数配置优化

openldap配置文件分为五部分

  • sladp进程配置部分
  • frontend:是一个特殊的 olcDatabaseConfig 配置提供权限认证
  • database:存储的真实引擎
  • backend:backend在slapd中不是真是的数据库,而是提供的一种转发方式

openldap目录布局

  • /etc/openldap/slapd.d/*/etc/openldap/slapd.ldif配置信息生成的文件,每修改一次配置信息,这里的东西就要重新生成。
  • /var/lib/ldap/*:OpenLDAP的数据文件。
  • /usr/share/openldap-servers/DB_CONFIG.example:模板数据库配置文件。
  • /usr/share/openldap-servers/slapd.ldif:默认模板配置文件。

默认OpenLdap服务所使用的端口为389,此端口采用明文传输数据,数据信息得不到保障。所以可以通过配置CA及结合TLS/SSL实现数据加密传输,所使用端口为636

1
cp /usr/share/openldap-servers/slapd.ldif /etc/openldap/

指定密码,不提示

1
2
$ slappasswd -s 111
{SSHA}QnB7dO98+hoCUgiaAYaiJWnDzlhn2Tn6
1
2
3
4
5
6
7
# 指定要搜索的后缀
olcSuffix: dc=cylon,dc=org
# rootdn,使用这个dn可以登录服务器
olcRootDN: cn=admin,dc=cylon,dc=org
olcDbDirectory: /var/lib/ldap
# 指定ldapserver管理员密码==
olcRootPW: {SSHA}QnB7dO98+hoCUgiaAYaiJWnDzlhn2Tn6

日志及缓存参数。

1
2
3
4
5
6
7
8
# 设置日志级别,记录日志信息方便调试 stats 256(日志连接/操作/结果) 
olcLogLevel: stats

# 设置ldap可以缓存的记录数
olcDbCacheSize: 1000

# checkpoint 可以吧内存中的数据写会数据文件的操作,此设置表示每达到2048kb或者10分钟执行一次
olcDbCheckpoint: 1024 10

开启扩展schema

openldap自带一些ldif文件 [10],LDIF 是 LDAP Data Interchange Format 的缩写,是作为存储与LDAP中 ” 文本格式 “ 的数据交换格式,每个条目代表的存入LDAP中记录的属性,记录之间用空行分隔,每行都是 “属性:值” 的格式,例如我们存入LDAP中一个记录,其属性有

  • dn (distinguished name) 用于标识目录中名称的唯一标识符
  • dc (domain component) 表示域组成,例如域名 www.mydomain.com 那么dc 应该配置为DC=www,DC=mydomain,DC=com
  • ou (organizational unit) 这是指用户的组织,这里也可以代表用户组,例如 OU=Lawyer,OU=Developer
  • cn (common name) 表示查询的个体对象的名称,这里可以代表用户名,服务名等,例如 cn=cylon

具有多个属性条目,在ldap中代表一条记录,例如

1
2
3
 dn: cn=The Postmaster,dc=example,dc=com
 objectClass: organizationalRole
 cn: The Postmaster

而ldif文件就是定义这些属性的文件,下面是openldap安装后默认的ldif文件说明:

  • collective.ldif Collective Attribute 组成LDAP条目的共享属性

  • corba.ldifCommon Object Request Broker Architecture 的缩写,旨在促进部署在不同平台上的系统的通信 [2]

  • cosine.ldifCooperation for Open Systems Interconnection Networking in Europe的缩写,用于给 cosineInternet X.500 模式项目提供LDAP中的属性格式 [3]

  • duaconf.ldifDirectory User Agents 的缩写,DUA是协议客户端,是向ldap或Internet X.500 DSA发起请求的一端,这是为DUA客户端提供了通用配置 [4]

  • dyngroup.ldifDynamic Group的缩写,动态组是LDAP中的一种组,与静态组相反,DG是以URL形式为搜索条件来隐式定义一组用户。[5]

    • 静态组 Static Groups 使用一组DN显式定义一组用户
  • inetorgperson.ldif:inetOrgPerson类是 RFC2798中 定义的类。在LDAP中为 user 的父类,比如说用户密码,登录时间等属性,更多可以参考 [6]

  • java.ldif:用于java的一些属性

  • misc.ldifMiscellaneous 的简写,这里主要是一些电子邮件相关属性

  • nis.ldifNetwork Information Service 的缩写,NIS是一种发现机制,这里是一种server-client的目录属性,例如网络中的主机名,用户名之类 [7]

  • openldap.ldif

  • pmi.ldifPrivilege Management Infrastructure 的缩写,是基于x.509的授权访问控制模型,这里是提供了基于PMI的一些属性

  • ppolicy.ldifpassword policy 的缩写,提供了增强的密码管理功能,例如账户到期时间,锁定等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
include: file:///etc/openldap/schema/collective.ldif   # OpenLDAP的核心schema必须
include: file:///etc/openldap/schema/corba.ldif # 
include: file:///etc/openldap/schema/cosine.ldif
include: file:///etc/openldap/schema/duaconf.ldif
include: file:///etc/openldap/schema/dyngroup.ldif
include: file:///etc/openldap/schema/inetorgperson.ldif
include: file:///etc/openldap/schema/java.ldif
include: file:///etc/openldap/schema/misc.ldif
include: file:///etc/openldap/schema/nis.ldif
include: file:///etc/openldap/schema/openldap.ldif
include: file:///etc/openldap/schema/pmi.ldif
include: file:///etc/openldap/schema/ppolicy.ldif

授权及安全参数配置

1
2
3
4
5
access to dn="cn=subschema" by * read
access to 
    by self write 
    by dn subtree="ou=sysusers,dc=test,dc=com" read
    by anonymous auth

关于更多权限管理的说明,可以参考官方手册第八章 [12]


提示:

参数在文件中的先后位置不能随意动。

空行和以“#”开头的注释行将被忽略。如果一行以空格开头,它将被认为是接着前一行的(即使前一行是注释)。


配置syslog记录ldap服务日志配置syslog

记录ldap服务日志,默认级别为256;

1
2
echo 'local4.*          /var/log/slapd.log' >> /etc/rsyslog.conf
local4.*                /var/log/slapd.log

配置LDAP数据库存放路径


注意

slapd.conf中设定了LDAP数据库格式为hdb,存储路径/var/1ib/ldap


1
2
3
4
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG

chown ldap.ldap /var/lib/ldap/DB_CONFIG
chmod 700 /var/lib/ldap/DB_CONFIG

整合的配置

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#
# See slapd-config(5) for details on configuration options.
# This file should NOT be world readable.
#

dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/openldap/slapd.args
olcPidFile: /var/run/openldap/slapd.pid
olcLogLevel: stats
olcDisallows: bind_anon
#
# TLS settings
#
olcTLSCACertificatePath: /etc/openldap/certs
olcTLSCertificateFile: "OpenLDAP Server"
olcTLSCertificateKeyFile: /etc/openldap/certs/password
#
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#
#olcReferral: ldap://root.openldap.org
#
# Sample security restrictions
#	Require integrity protection (prevent hijacking)
#	Require 112-bit (3DES or better) encryption for updates
#	Require 64-bit encryption for simple bind
#
#olcSecurity: ssf=1 update_ssf=112 simple_bind=64

#
# Load dynamic backend modules:
# - modulepath is architecture dependent value (32/64-bit system)
# - back_sql.la backend requires openldap-servers-sql package
# - dyngroup.la and dynlist.la cannot be used at the same time
#

#dn: cn=module,cn=config
#objectClass: olcModuleList
#cn: module
#olcModulepath:	/usr/lib/openldap
#olcModulepath:	/usr/lib64/openldap
#olcModuleload: accesslog.la
#olcModuleload: auditlog.la
#olcModuleload: back_dnssrv.la
#olcModuleload: back_ldap.la
#olcModuleload: back_mdb.la
#olcModuleload: back_meta.la
#olcModuleload: back_null.la
#olcModuleload: back_passwd.la
#olcModuleload: back_relay.la
#olcModuleload: back_shell.la
#olcModuleload: back_sock.la
#olcModuleload: collect.la
#olcModuleload: constraint.la
#olcModuleload: dds.la
#olcModuleload: deref.la
#olcModuleload: dyngroup.la
#olcModuleload: dynlist.la
#olcModuleload: memberof.la
#olcModuleload: pcache.la
#olcModuleload: ppolicy.la
#olcModuleload: refint.la
#olcModuleload: retcode.la
#olcModuleload: rwm.la
#olcModuleload: seqmod.la
#olcModuleload: smbk5pwd.la
#olcModuleload: sssvlv.la
#olcModuleload: syncprov.la
#olcModuleload: translucent.la
#olcModuleload: unique.la
#olcModuleload: valsort.la


#
# Schema settings
#

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

include: file:///etc/openldap/schema/core.ldif
include: file:///etc/openldap/schema/collective.ldif
include: file:///etc/openldap/schema/corba.ldif
include: file:///etc/openldap/schema/cosine.ldif
include: file:///etc/openldap/schema/duaconf.ldif
include: file:///etc/openldap/schema/dyngroup.ldif
include: file:///etc/openldap/schema/inetorgperson.ldif
include: file:///etc/openldap/schema/java.ldif
include: file:///etc/openldap/schema/misc.ldif
include: file:///etc/openldap/schema/nis.ldif
include: file:///etc/openldap/schema/openldap.ldif
include: file:///etc/openldap/schema/pmi.ldif
include: file:///etc/openldap/schema/ppolicy.ldif

#
# Frontend settings
#
# 这里是对前端权限的配置,通常默认,不添加权限
dn: olcDatabase=frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: frontend
#
# 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!
#

#
# Configuration database
#
# 这里是对后端数据库权限的配置
dn: olcDatabase=config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: config
olcAccess: to attrs=userPassword,shadowLastChange
    by dn.children="cn=admin,dc=test,dc=com" write
    by anonymous auth
    by self write
    by * none
olcAccess: to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
    by group.exact="cn=configadmin,ou=admin,dc=seal,dc=com" write
    by * none

#
# Server status monitoring
#

dn: olcDatabase=monitor,cn=config
objectClass: olcDatabaseConfig
olcDatabase: monitor
olcAccess: to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,c
 n=auth" read by dn.base="cn=Manager,dc=my-domain,dc=com" read by * none

#
# Backend database definitions
#
# 这里是数据库的参数配置
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
# 使用的数据库引擎是mdb
objectClass: olcMdbConfig
olcDatabase: mdb
# Suffix 为数据库的后缀,每个数据库至少一个,在搜索时-D 后面的域后缀为dc=test,dc=com将被pass到这里
olcSuffix: dc=test,dc=com
# 指不收前面配置的权限控制的管理员账户,拥有最最高权限
olcRootDN: cn=admin,dc=test,dc=com
# 特权账户的登录密码
olcRootPW: {SSHA}xU9xFym/s7rawpmzpsYE+Q1qPsVPOwDw
olcDbDirectory:	/var/lib/ldap
# 这是索引属性,下面是默认的属性
# 下列注释行意思为
#        olcDbIndex: default pres,eq
#        olcDbIndex: uid
#        olcDbIndex: cn,sn pres,eq,sub
#        olcDbIndex: objectClass eq
# pres,eq 为 present equality
# 第二行意思为,为uid属性类型维护默认索引集
# 第三行意思为,为cn,sn属性维护pres,eq,sub索引集
# 索引集类型有 pres,eq,approx,sub,none
olcDbIndex: objectClass eq,pres
olcDbIndex: uid,ou,cn,mail,surname,givenname eq,pres,sub
# 配置从缓冲区写入磁盘的,两个参数分别为多少kbyte大小的数据自上次(第二个参数)分钟则发生一次写入
olcDbCheckpoint: 1024 10

更多配置文件选项说明可以参考 [14]

生成配置文件

修改配置文件后需要重新生成配置文件

1
slapadd -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif

生成配置文件时的错误

1
2
3
4
$ slapadd -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif
63678619 str2entry: entry -1 has no dn
slapadd: could not parse entry (line=31)
_########              43.66% eta   none elapsed            none spd   7.0 M/s 

对于 slapd.ldif 需要注意下列事项

  • 行首 # 为注释
  • 行尾不能有任何空白,这里也是很难排查的一个点
  • 对于不同的属性需要放对位置快否则会报错,例如 olcDbCacheSize: 1000 是hdb配置,mdb添加会报错,有明显提示
  • 如果生产配置失败后,修改配置文件后再次生成需要删除 rm -fr slapd.d/*

例如下面就是一个有提示的典型例子

1
2
63678513 Entry (cn=config), attribute 'olcDbCacheSize' not allowed
slapadd: dn="cn=config" (line=1): (65) attribute 'olcDbCacheSize' not allowed

下面的报错比较不明显,通常删除 rm -fr slapd.d/* 后重试

1
2
slapadd: could not add entry dn="cn=config" (line=1): 
_###                   17.92% eta   none elapsed            none spd   6.3 M/s 

为LDAP初始化数据

部署完成后就是访问,ldap了,此时向OpenLDAP 搜索会发现没有内容

1
2
3
4
$ ldapsearch -LLL -x -W -H ldap://10.0.0.4 -D "cn=admin,dc=test,dc=com" -b "dc=test,dc=com" "(uid=*)"

Enter LDAP Password: 
No such object (32)

Reference

创建Root条目

在第一次部署好openldap中,实际上是没有任何条目的,此时是无法存入数据,有人说在 database setting中配置了 olcRootDN ,这里是指标识用哪个数据库的(即那个root存入哪里),而不是一个具体的root dn,所以需要手动创建一个

例如下列,是创建一个RootDN

1
2
3
4
5
6
7
8
cat << EOF | ldapadd -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -w 111
dn: dc=test,dc=com
objectclass: top
objectClass: organizationalUnit
objectclass: extensibleObject
description: US Organization
ou: people
EOF

这里需要注意几点:

  • dn: dc=test,dc=com 是指定存储的地方,如果在database配置中为配置 olcRootDN 则报错不会被存储
  • 由于创建的的是root,所以ou的 objectClass 会报错,需要用一个 extensibleObject 才可以创建 [15]

创建子域

此时因为有了RootDN,可以指定dn为子域了,并且 objectClass: organizationalUnit 可以单独使用

这里子域其实可以理解为二级域名了,在公司中也可以为子公司

1
2
3
4
5
cat << EOF | ldapadd -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -w 111
dn: ou=group,dc=test,dc=com
objectClass: organizationalUnit
ou: group
EOF

创建组

这里使用 posixGroup Portable Operating System Interface of UNIX 的简写,这里可以理解为Linux用户管理的标准,包含一些标准的属性,类似于 /etc/group

下面创建一个gid为10001的组,组名为tech

1
2
3
4
5
6
cat << EOF | ldapadd -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -w 111
dn: cn=tech,ou=group,dc=test,dc=com
objectClass: posixGroup
gidNumber: 10001
cn: tech
EOF

创建用户

创建用户user01

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cat << EOF | ldapadd -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -w 111
dn: uid=user01,ou=Group,dc=test,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
homeDirectory: /home/user01
loginShell: /bin/bash
uid: user01
cn: user01
uidNumber: 10004
gidNumber: 10001
userPassword: {SSHA}hJpIIVxj1qS9g05qUlgG+o7MO14EXbFQ
sn: user01
givenName: user01

创建用户cylon

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cat << EOF | ldapadd -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -w 111
dn: uid=cylon,ou=Group,dc=test,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
homeDirectory: /home/cylon
loginShell: /bin/bash
uid: cylon
cn: cylon
userPassword: {SSHA}2pvE4C6xy8dkmW2aD/eEocVajg8BujWW
uidNumber: 10005
gidNumber: 10001
sn: cylon
EOF

如上面所示,objectClass [11] 表示这个ldap条目拥有的属性,可以看到 posixAccountinetOrgPerson 等都是导入的schema文件,其中 uidNumberuserPassword 都是 NIS 定义的,cn 则是 core定义的


提示:

  • 以上信息中ldap
    • 用户1:user01密码 111
    • 用户2:cylon 密码 123456
  • 这些原始信息是如何获得的?

检查初始化测试数据。

查询导入的结果,默认查的是所有数据

1
ldapsearch -LLL -w 111 -x -H ldap://10.0.0.3 -D "cn=admin,dc=test,dc=com" -b "dc=test,dc=com"

备份ldap数据库数据

1
2
ldapadd -x -H ldap://cylon.org -D "cn=admin,dc=cylon,dc=org" -W -f base.ldif >base.ldif
ldapadd -x -H ldap://cylon.org -D "cn=admin,dc=cylon,dc=org" -W -f test.ldif >test.ldif

Reference

[1] msg00281

[2] Object Request Broker Architecture

[3] Cooperation for Open Systems Interconnection Networking in Europe

[4] DUA

[5] DynamicGroup

[6] InetOrgPerson

[7] Network Information Service

[8] Privilege Management Infrastructure

[9] Password Policy

[10] LDAP Data Interchange Format

[11] Object Class

[12] 8. Access Control

[13] openldap system requirements for virtualization

[14] slapdconf2

[15] attribute dc is not allowed

本文发布于Cylon的收藏册,转载请著名原文链接~

链接:理解ldap - OpenLDAP安装

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。