LDAP 服务
本文主要在debian配置,如果需要在CentOS上部署,需要修改大部分的路径,这里需要自行修改。
LDAP
服务按照个人理解,也可使理解为一个数据库,但是这个数据库的读写性能不像 MySQL
一样拥有良好的读写性能,而 LDAP
更偏向于读取,而弱于写入。并且 LDAP
的数据类型属于面向对象的数据类型,这和 MySQL
的数据类型不同,并且使用树状结构记录数据,这些都与普通的数据库(关系型数据库),有着极大的差别。而这一切的一切都代表着 LDAP
这个服务并不是用做一个普通的数据库(关系型数据库)用的,而是用于类似于账户存储等这种少存入、多读取、需要包含对象类型和对象相关属性的场合。
LDAP工作机制
就跟上面说的一样,LDAP是树状结构的数据库,所以说如果想要找到其中一个节点,就得通过逐层查询,并且必须保证每一个节点的路径唯一,那么这个节点的路径就称之为dn,dn 的编写路径必须是由下而上编写的,例如:
cn=scott,ou=marketing,ou=people,dc=mydomain,dc=org
关键字 | 英文全称 | 含义 |
---|---|---|
dc | Domain Component | 域名的部分,其格式是将完整的域名分成几部分,如域名为 example.com 那么就是: dc=example,dc=com |
uid | User Id | 用户 ID,如 “tom” |
ou | Organization Unit | 组织单位,类似于 Linux 文件系统中的子目录,它是一个容器对象,组织单位可以包含其他各种对象(包括其他组织单元),如 “market” |
cn | Common Name | 公共名称,如 “Thomas Johansson” |
sn | Surname | 姓,如 “Johansson” |
c | Country | 国家,如 “CN” 或“US”等。 |
o | Organization | 组织名,如 “Example, Inc.” |
dn | Distinguished Name | 惟一辨别名,类似于 Linux 文件系统中的绝对路径,每个对象都有一个惟一的名称,如 “uid= tom,ou=market,dc=example,dc=com”,在一个目录树中 DN 总是惟一的 |
rdn | Relative dn | 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如 “uid=tom” 或“cn= Thomas Johansson” |
以上这些类别没有指定特定的用法,这些完全由应用程序自行决定。
LDAP 安装
debian:
代码语言:javascript复制apt install slapd ldap-utils # slapd 为服务端, ldap-utils 为客户端程序
CentOS:
代码语言:javascript复制yum install openldap-servers openldap-clients # 上同
LDAP 服务器配置初始化
做这一步的目的是为了完全自定义初始化数据库,抛弃由软件包构成的数据库。 当然你也可以跳过这个步骤,直接开始下一步,这样也是无所谓的。
你也可以你使用 debian 提供的便捷方式来完成服务器配置: dpkg-reconfig slapd
首先先来解释一些为什么要按照如下(完全属于个人理解):
新版的 OpenLdap 已经弃用了 slapd.conf 配置文件,改而使用 slapd.d 目录下的树状目录文件来配置服务器的相关配置。但是 slapd.d 是由服务进程维护的,并且使用CRC来校验文本是否改动,我们无法轻易修改,slapd安装包给我们提供了一个命令 slapadd
用于创建配置文件,所以才用了下面的方法来初始化数据库。后期使用 ldapmodify
或 ldapadd
来完成服务器配置。
首先停止数据库服务:
代码语言:javascript复制systemctl stop slapd
然后编辑文件:
代码语言:javascript复制# 首先备份文件,以免无法复原
mkdir /root/back
tar -Jcvf /root/back/slapd.config-`date ' (%Y.%m.%d_%H:%M:%S)'`.tar.xz /etc/ldap/slapd.d/
tar -Jcvf /root/back/slapd.data-`date ' (%Y.%m.%d_%H:%M:%S)'`.tar.xz /var/lib/ldap /var/lib/slapd
# 然后再删除配置文件
rm -rf /etc/ldap/slapd.d/*
rm -rf /var/lib/slapd/*
rm -rf /var/lib/ldap/*
# 复制配置文件到临时目录
cp /usr/share/slapd/slapd.init.ldif /tmp
cd /tmp
这里我创建一个sed的规则表,方便使用,以下请自行选择。
代码语言:javascript复制# file: rules
##################################
# 本文请自行选择复制到到文件内 #
##################################
#自定义基本域名(必选):
s/@SUFFIX@/$(basename)/g
#自定义管理员用户密码(必须):
s/@PASSWORD@/$(password)/g
#自定义管理员用户名称(可选):
s/cn=admin/cn=$(username)/g
#数据库类型(3选1,必选):
# mdb
s/@BACKEND@/mdb/g
s/@BACKENDOBJECTCLASS@/olcMdbConfig/g
s/@BACKENDOPTIONS@/olcDbMaxSize: 1073741824/g
# hdb
s/@BACKEND@/hdb/g
s/@BACKENDOBJECTCLASS@/olcHdbConfig/g
s/@BACKENDOPTIONS@/olcDbConfig: set_cachesize 0 2097152 0nolcDbConfig: set_lk_max_objects 1500nolcDbConfig: set_lk_max_locks 1500nolcDbConfig: set_lk_max_lockers 1500/g
# bdb
s/@BACKEND@/bdb/g
s/@BACKENDOBJECTCLASS@/olcBdbConfig/g
s/@BACKENDOPTIONS@/olcDbConfig: set_cachesize 0 2097152 0nolcDbConfig: set_lk_max_objects 1500nolcDbConfig: set_lk_max_locks 1500nolcDbConfig: set_lk_max_lockers 1500/g
这里我选择hdb数据库,样例如下:
代码语言:javascript复制# file:rule
s/@SUFFIX@/dc=black,dc=com/g
s/@PASSWORD@/{SSHA}RadcVPriXsR6gCwhwPKsCLkhnHy3r1ZS/g
s/cn=admin/cn=root/g
s/@BACKEND@/hdb/g
s/@BACKENDOBJECTCLASS@/olcHdbConfig/g
s/@BACKENDOPTIONS@/olcDbConfig: set_cachesize 0 2097152 0nolcDbConfig: set_lk_max_objects 1500nolcDbConfig: set_lk_max_locks 1500nolcDbConfig: set_lk_max_lockers 1500/g
其中密码是这样生成的:
代码语言:javascript复制slappasswd -s 147258369
{SSHA}RadcVPriXsR6gCwhwPKsCLkhnHy3r1ZS
再然后通过命令修改配置文件,并且生成配置文件和数据库:
代码语言:javascript复制sed -i -f rule /tmp/slapd.init.ldif
slapadd -F "/etc/ldap/slapd.d/" -b "cn=config" -l slapd.init.ldif
_#################### 100.00% eta none elapsed none fast! Closing DB...
我们再查看一下这些文件的:
代码语言:javascript复制ll /etc/ldap/slapd.d/*
-rw------- 1 root root 478 Jul 10 09:06 /etc/ldap/slapd.d/cn=config.ldif /etc/ldap/slapd.d/cn=config: total 28 -rw------- 1 root root 452 Jul 10 09:06 cn=module{0}.ldif drwxr-x--- 2 root root 4096 Jul 10 09:06 cn=schema -rw------- 1 root root 394 Jul 10 09:06 cn=schema.ldif -rw------- 1 root root 412 Jul 10 09:06 olcBackend={0}hdb.ldif -rw------- 1 root root 542 Jul 10 09:06 olcDatabase={0}config.ldif -rw------- 1 root root 657 Jul 10 09:06 olcDatabase={-1}frontend.ldif -rw------- 1 root root 1084 Jul 10 09:06 olcDatabase={1}hdb.ldif
哦,我们这里看到了好像文件权限不对啊,所以我们也改改文件属主。
代码语言:javascript复制chown -R openldap:openldap slapd.d
chown -R openldap:openldap /var/lib/slapd/*
chown -R openldap:openldap /var/lib/ldap/*
那么这里就可以正常启动服务器了:
代码语言:javascript复制systemctl start slapd
LDAP 数据库创建
这里我们还需要注意虽然前面创建的服务器配置里有DN信息,但是真正的数据库完全没有创建,这里我们必须手动创建这些数据库。当然你可以使用命令 slapcat
或者 ldapsearch
命令来查询是否有数据存在。
首先创建一个文件,用于记录需要存入的数据,ldap数据库没有交互式界面,每一次操作都必须一条命令,其实这也侧面证明了LDAP是是个偏读取的面向对象型的服务,而不是一个综合型的数据库服务。
代码语言:javascript复制# file:base.ldif
# 根节点 复制时,注意把这这个注释删了!!!!
dn: dc=black,dc=com
dc: black
objectClass: top
objectClass: domain
# 管理员用户root
dn: cn=root,dc=black,dc=com
objectClass: organizationalRole
cn: root
description: LDAP Manager
然后我们再通过命令,将 base.ldif
这的信息导入至数据库
ldapadd -x -D "cn=root,dc=black,dc=com" -w 147258369 -f base.ldif
adding new entry "dc=black,dc=com" adding new entry "cn=root,dc=black,dc=com"
这里需要解释一项这里命令的基本用法:
- -x: 表示使用基本拥挤认证
- -D "cn=root,dc=black,dc=com" -w 147258369: 指定用户和密码
- -f: 指定文件
那么这里再验证一下数据库是否创建成功:
代码语言:javascript复制ldapsearch -x -D "cn=root,dc=black,dc=com" -w 147258369 -b "dc=black,dc=com"
# extended LDIF # # LDAPv3 # base <dc=black,dc=com> with scope subtree # filter: (objectclass=*) # requesting: ALL # # black.com dn: dc=black,dc=com dc: black objectClass: top objectClass: domain # root, black.com dn: cn=root,dc=black,dc=com objectClass: organizationalRole cn: root description: LDAP Manager # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2
再解释一个参数:
- -b: 指定需要搜索的base目录
LDAP 后期管理
数据库管理#
这里的数据库管理也可是使用一些 LDAP 软件来完成(部署 LDAP 应用),不过还以要写写命令行,因为命令行的灵活性高,而且便于理解,这些都是应用程序无法比拟的。
ldapadd 条目���加#
还是和上面数据库创建一样的,需要先创建一个文件用于存放数据。
代码语言:javascript复制# file: group.ldif
# 组织单元
dn: ou=User,dc=black,dc=com
objectClass: organizationalUnit
ou: User
# 用户1
dn: uid=User1,ou=User,dc=black,dc=com
objectClass: account
objectClass: simpleSecurityObject
uid: User1
userPassword: {SSHA}5WjJz9QfntUjurHirfv9C4832x1xh9Kt
# 用户2
dn: uid=User2,ou=User,dc=black,dc=com
objectClass: account
objectClass: simpleSecurityObject
uid: User2
userPassword: {SSHA}9biML BP/W8w3mRkVack7CyB1hfDi8cD
然后我们再通过命令将文件添加到数据库:
代码语言:javascript复制ldapadd -x -D "cn=root,dc=black,dc=com" -w 147258369 -f group.ldif
adding new entry "ou=User,dc=black,dc=com" adding new entry "uid=User1,ou=User,dc=black,dc=com" adding new entry "uid=User2,ou=User,dc=black,dc=com"
ldapadd 可以从文件中读取数据,同时也可从标准输入输出读取数据:
代码语言:javascript复制cat << EOF | ldapadd -x -D "cn=root,dc=black,dc=com" -w 147258369
dn: uid=User3,ou=User,dc=black,dc=com
objectClass: account
objectClass: simpleSecurityObject
uid: User3
userPassword: {SSHA}iES3qeH0nYUcwGtSQm1hIBCEsV gBF3P
EOF
adding new entry "uid=User3,ou=User,dc=black,dc=com"
这样就可以临时添加数据了,同时这样也可使用bash脚本完成批量用户添加,这里我就不演示了。
ldapmodify 条目更改#
还是一样的将数据写入文件,不过这里需要注意,因为是更改条目,所以需要编写指明更改模式,和更改目标。
代码语言:javascript复制# file: change.ldif
dn: uid=User3,ou=User,dc=black,dc=com
changetype: modify
replace: userPassword
userPassword: {SSHA}9TM5y06bvepK6k8i Jfkc/9C6GkVsobm
然后使用命令即可。
代码语言:javascript复制ldapmodify -x -D "cn=root,dc=black,dc=com" -w 147258369 -f change.ldif
modifying entry "uid=User3,ou=User,dc=black,dc=com"
那么再来验证一下:
代码语言:javascript复制ldapwhoami -x -D "uid=User3,ou=User,dc=black,dc=com" -w 147
dn:uid=User3,ou=User,dc=black,dc=com
如果返回如上,那么修改成功。
ldapdelete 条目删除#
删除条目不需要写清除如何如何,只需要指定条目路径即可,也就是dn.
代码语言:javascript复制ldapdelete -x -D "cn=root,dc=black,dc=com" -w 147258369 "uid=User3,ou=User,dc=black,dc=com"
这个命令没有返回信息,那么表明执行成功。我们再次使用命令验证:
代码语言:javascript复制ldapwhoami -x -D "uid=User3,ou=User,dc=black,dc=com" -w 123456
ldap_bind: Invalid credentials (49)
这就返回凭据无效则表明条目删除成功。
ldapsearch 条目搜寻#
这个就不多说了,直接上命令:
代码语言:javascript复制ldapsearch -x -b "dc=black,dc=com" -D "cn=root,dc=black,dc=com" -w 147258369 "(&(objectclass=account)(uid=User1))" # 这里最后一段是filter,用于过滤查询结果
# extended LDIF # # LDAPv3 # base <dc=black,dc=com> with scope subtree # filter: (objectclass=*) # requesting: ALL # # User1, User, black.com dn: uid=User1,ou=User,dc=black,dc=com objectClass: account objectClass: simpleSecurityObject userPassword:: e1NTSEF9OWJpTUwrQlAvVzh3M21Sa1ZhY2s3Q3lCMWhmRGk4Y0Q= uid: User1 # search result search: 2 result: 0 Success # numResponses: 6 # numEntries: 5
-b:指定基本路径,会查找该路径下的所有节点
ldapwhomai 用户查询#
前面也用过了,直接上命令:
代码语言:javascript复制ldapwhoami -x -D "cn=root,dc=black,dc=com" -w 147258369
dn:cn=root,dc=black,dc=com
返回值如上则表示正常
服务器配置#
这里服务器的后续配置,不能再动 slapd.d 目录下的文件了,必须通过 ldap 提供的 API 接口完成服务器配置,这点是非常重要的。所以我们还需要通过客户端命令 ldapmodify 命令来进行服务配置,比如所修改管理员密码:
这里的dn节点与数据库节点不同,你可以看到这些条目对应的就是 slapd.d 目录下的文件了,当然是去去除了后缀名(ldif)的节点。
代码语言:javascript复制# file: config.ldif
dn: olcDatabase={1}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}5WjJz9QfntUjurHirfv9C4832x1xh9Kt
然后通过命令完成修改:
代码语言:javascript复制 ldapmodify -Y EXTERNAL -H ldapi:/// -f config.ldif
SASL/EXTERNAL authentication started SASL username: gidNumber=0 uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={1}hdb,cn=config"
注:如果节点不存在,但是你还是想要创建也是可是的,你需要将dn节点指定到你需要创建的文件路径,然后使用命令ldapadd 添加即可。
LDAP 备份和还原#
这里我使用了 slapd 提供的命令完成了该操作,主要就是方便而且全面,也不想去了解别的方法,都没这个实在。
服务器备份#
代码语言:javascript复制slapcat -n 0 -l slapcat.bak.0.ldif # 0 表示备份服务器配置
slapcat -n 1 -l slapcat.bak.1.ldif # 1 表示备份数据库
无返回信息则表示执行成功。
服务器还原#
关闭服务器:
代码语言:javascript复制systemctl stop slapd
删除原始文件:
代码语言:javascript复制# 首先备份文件,以免无法复原
mkdir /root/back
tar -Jcvf /root/back/slapd.config-`date ' (%Y.%m.%d_%H:%M:%S)'`.tar.xz /etc/ldap/slapd.d/
tar -Jcvf /root/back/slapd.data-`date ' (%Y.%m.%d_%H:%M:%S)'`.tar.xz /var/lib/ldap /var/lib/slapd
# 然后再删除配置文件
rm -rf /etc/ldap/slapd.d/*
rm -rf /var/lib/slapd/*
rm -rf /var/lib/ldap/*
还原数据库:
代码语言:javascript复制slapadd -l slapcat.bak.0.ldif -F /etc/ldap/slapd.d/ -b "cn=config" # 还原服务器配置
slapadd -l slapcat.bak.1.ldif -F /etc/ldap/slapd.d/ # 还原数据库
_#################### 100.00% eta none elapsed none fast! Closing DB... _#################### 100.00% eta none elapsed none fast! Closing DB...
这样就搞定了。 但是还是需要注意权限:
代码语言:javascript复制chown -R openldap:openldap /etc/ldap/slapd.d/*
chown -R openldap:openldap /var/lib/slapd/*
chown -R openldap:openldap /var/lib/ldap/*
启动服务器:
代码语言:javascript复制systemctl start slapd
部署 LDAP 应用
这里直接使用 phpldapadmin了, 我也不想再多弄了,怎么简单,怎么来了。
代码语言:javascript复制apt install phpldapadmin
然后配置一下 phpladpadmin的文件即可:
代码语言:javascript复制# file: /etc/phpldap/config.php
……
$servers->setValue('server','base',array('dc=black,dc=com')); # 在300行,更改服务器
……
……
$servers->setValue('login','bind_id','cn=root,dc=black,dc=com'); # 在326行,更改登入的默认字符串
……
然后登入即可:
界面如下: