一、背景
OpenLDAP是开源的目录服务实现,AD是微软的目录服务现实。在我们的业务环境中可能会出现有的应用场景(应用、客户端)跟OpenLDAP结合比较容易;有的应用场景又必须要使用AD。几乎不可能弃用其中的任意一种。但同时维护两套系统意味着维护工作大量增加(不仅仅只是增加一倍,要考虑信息分别维护、同步等)、出错几率大大增加。
其中的一种较成熟、使用比较多的解决方案是:OpenLDAP使用AD的认证,即只在AD上维护一套用户密码,OpenLDAP将认证转发到微软AD上进行。
二、相关组件
- LDAP Client:这个是实际调用ldap服务的系统,也可以是类似ldapsearch之类的client程序
- OpenLDAP服务器:开源服务端,实际进程为slapd (OpenLDAP 2.4.44)
- saslauthd :简单认证服务层的守护进程,该进程要安装在openldap服务器上 (cyrus-sasl-2.1.26)
- AD:微软AD
三、部署
1、安装OpenLdap
(1)安装OpenLDAP服务
注:本文仅以OpenLDAP 2.4.44版本为例进行安装和配置说明,其他版本如有差异请以实际为准。
[root@localhost ~]# yum install -y openldap openldap-clients openldap-servers-sql compat-openldap openldap-devel openldap-servers
[root@localhost ~]# systemctl restart slapd.service
[root@localhost ~]# systemctl enable slapd.service
(2)配置OpenLDAP管理密码
并修改openldap配置
[root@localhost ~]# slappasswd
New password:
Re-enter new password:
{SSHA}XTelJmyJk2XEG/hA+E5UpHvO4Z89b7n7
把上面生成的{SSHA}开头的字符串记下来,后面修改配置文件要用
# 新建一个ldif文件用于修改openldap配置
[root@localhost ~]# vim change_ldap_cfg.ldif
# 将以下内容写入
# 实际配置的时候建议把“#”后面的注释内容删掉,只保留配置内容
dn: olcDatabase={2}hdb,cn=config
changetype: modify # 表示我们需要为这个文件执行变更操作
replace: olcRootDN # 修改olcRootDN这个字段的内容
olcRootDN: cn=Manager,dc=test,dc=winad,dc=com # 把olcRootDN这个字段的内容修改成这样
- # 具体含义不知道,但是大概表示上面这个dn的配置还没修改完,下面还是修改这个dn的配置
replace: olcSuffix # 修改olcSuffix这个字段的内容
olcSuffix: dc=test,dc=winad,dc=com # 把olcSuffix这个字段的内容修改成这样
-
add: olcRootPW # 增加一个olcRootPW字段
olcRootPW: {SSHA}XTelJmyJk2XEG/hA+E5UpHvO4Z89b7n7 # 第2步生成的密码,增加的olcRootPW这个字段的内容是这样
dn: olcDatabase={1}monitor,cn=config # 表示修改/etc/openldap/slapd.d/cn=config/olcDatabase={1}monitor.ldif这个文件里的内容
changetype: modify # 表示我们需要为这个文件执行变更操作
replace: olcAccess # 修改olcAccess这个字段的内容
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth" read by dn.base="cn=Manager,dc=test,dc=winad,dc=com" read by * none # 把olcAccess这个字段的内容修改成这样
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=huawang,dc=com
-
replace: olcSuffix
olcSuffix: dc=huawang,dc=com
-
add: olcRootPW
olcRootPW: {SSHA}XTelJmyJk2XEG/hA+E5UpHvO4Z89b7n7
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth" read by dn.base="cn=Manager,dc=huawang,dc=com" read by * none
上面的配置文件保存好之后,执行ldapmodify命令进行修改
[root@localhost ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f change_ldap_cfg.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={2}hdb,cn=config"
modifying entry "olcDatabase={1}monitor,cn=config"
执行完了以后看下下面这两个文件,看看需要修改的字段改过来没有
/etc/openldap/slapd.d/cn=config/olcDatabase={1}monitor.ldif
/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif
(3)创建管理员账号
新建一个ldif文件用于导入管理员账号
[root@localhost ~]# vim base.ldif
# 添加以下内容
dn: dc=huawang,dc=com
o: huawang com
dc: huawang
objectClass: top
objectClass: dcObject
objectclass: organization
dn: cn=Manager,dc=huawang,dc=com
cn: Manager
objectClass: organizationalRole
description: Directory Manager
上面的配置文件保存好之后,执行ldapadd命令导入
导入账号
[root@localhost ~]# ldapadd -x -D "cn=Manager,dc=huawang,dc=com" -W -f base.ldif
Enter LDAP Password: # 这里输的密码就是上面第二步的时候配置的那个密码
adding new entry "dc=huawang,dc=com"
adding new entry "cn=Manager,dc=huawang,dc=com"
(4)配置DB数据库
[root@localhost ~]# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
[root@localhost ~]# chown ldap:ldap -R /var/lib/ldap
[root@localhost ~]# chmod 700 -R /var/lib/ldap
(5)验证OpenLDAP配置文件
是否正确
[root@localhost ~]# slaptest -u
config file testing succeeded #验证成功,如果是返回其他内容则失败。
(6)给相关目录授权
否则启动服务时可能会报错,权限不足
[root@localhost ~]# chown ldap:ldap -R /var/run/openldap
[root@localhost ~]# chown ldap:ldap -R /etc/openldap/
(7)导入schema
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/collective.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/corba.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/duaconf.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/dyngroup.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/java.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/misc.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/openldap.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/pmi.ldif
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/ppolicy.ldif
(8)添加memberOf模块
因为我们是要和WindowsAD联动,所以需要将权限组这个模块提前准备好。如果提前没有准备好,后面再加的话,还得把建好的组全删掉再重建。这个模块的作用是当你建一个组的时候,把一些用户添加到这个组里去,它会自动给这些用户添加一个memberOf属性,有很多应用需要检查这个属性。
添加的时候比较麻烦,需要建3个ldif文件,然后1个执行ldapmodify,2个执行ldapadd,注意顺序,不能出错
新建一个memberof_config.ldif文件
[root@localhost ~]# vim memberof_config.ldif
# 在文件中写入以下内容
dn: cn=module,cn=config
cn: module
objectClass: olcModuleList
olcModuleLoad: memberof
olcModulePath: /usr/lib64/openldap # 这里请注意,请确认/usr/lib64/目录下是否有openldap目录
dn: olcOverlay={0}memberof,olcDatabase={2}hdb,cn=config # 这个意思是说在/etc/openldap/slapd.d/cn=config/目录下创建一个olcDatabase={2}hdb目录,然后在里面再创建一个olcOverlay={0}memberof.ldif文件
objectClass: olcConfig
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: top
olcOverlay: memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
文件保存好之后,执行ldapadd命令
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_config.ldif
执行完之后,检查你的/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb/目录下,看是不是多了一个olcOverlay={0}memberof.ldif模块
[root@ad-passwd (13:57:34)~]# ll /etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb/
总用量 4
-rw------- 1 ldap ldap 700 11月 6 13:55 olcOverlay={0}memberof.ldif
然后检查你的/etc/openldap/slapd.d/cn=config/目录下,看是不是多了一个cn=module{0}.ldif模块,这个模块的数字编号直接影响下一步操作。
[root@ad-passwd (13:58:18)~]# ll /etc/openldap/slapd.d/cn=config/
总用量 28
-rw-------. 1 ldap ldap 534 11月 7 14:28 cn=module{0}.ldif
drwxr-x---. 2 ldap ldap 4096 11月 7 14:26 cn=schema
-rw-------. 1 ldap ldap 378 11月 6 18:08 cn=schema.ldif
-rw-------. 1 ldap ldap 513 11月 6 18:08 olcDatabase={0}config.ldif
-rw-------. 1 ldap ldap 443 11月 6 18:08 olcDatabase={-1}frontend.ldif
-rw-------. 1 ldap ldap 606 11月 7 14:05 olcDatabase={1}monitor.ldif
drwxr-x---. 2 ldap ldap 41 11月 7 14:28 olcDatabase={2}hdb
-rw-------. 1 ldap ldap 716 11月 7 14:05 olcDatabase={2}hdb.ldif
新建一个refint1.ldif文件
[root@localhost ~]# vim refint1.ldif
# 在文件中写入以下内容
dn: cn=module{0},cn=config # 这里的意思就是我们上面说的那个/etc/openldap/slapd.d/cn=config/目录下的cn=module{0}.ldif,我们这一次要修改这个文件
add: olcmoduleload
olcmoduleload: refint
如果你那边不是module{0}的话,那就看是几,是几就写几就行了,对于这个文件,我们要执行ldapmodify操作:
[root@localhost ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f refint1.ldif
接下来新建一个refint2.ldif文件
[root@localhost ~]# vim refint2.ldif
dn: olcOverlay={1}refint,olcDatabase={2}hdb,cn=config # 在/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb目录下,再创建一个olcOverlay={1}refint.ldif文件
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: {1}refint
olcRefintAttribute: memberof member manager owner
对这个文件执行ldapadd操作:
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f refint2.ldif
重启slapd服务
# systemctl restart slapd.service
# systemctl status slapd.service
● slapd.service - OpenLDAP Server Daemon
Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
Active: active (running) since 一 2023-11-06 14:24:01 CST; 5s ago
Docs: man:slapd
man:slapd-config
man:slapd-hdb
man:slapd-mdb
file:///usr/share/doc/openldap-servers/guide.html
Process: 37076 ExecStart=/usr/sbin/slapd -u ldap -h ${SLAPD_URLS} $SLAPD_OPTIONS (code=exited, status=0/SUCCESS)
Process: 37022 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS)
Main PID: 37105 (slapd)
Tasks: 2
Memory: 15.6M
CGroup: /system.slice/slapd.service
└─37105 /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///
11月 06 14:24:01 ad-passwd runuser[37042]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd runuser[37042]: pam_unix(runuser:session): session closed for user ldap
11月 06 14:24:01 ad-passwd runuser[37044]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd runuser[37050]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd runuser[37054]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd runuser[37060]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd runuser[37069]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
11月 06 14:24:01 ad-passwd slapd[37076]: @(#) $OpenLDAP: slapd 2.4.44 (Feb 23 2022 17:11:27) $
mockbuild@x86-01.bsys.centos.org:/builddir/build/BUILD/openldap-2.4.44/openldap-2.4.44/servers/slapd
11月 06 14:24:01 ad-passwd slapd[37105]: slapd starting
11月 06 14:24:01 ad-passwd systemd[1]: Started OpenLDAP Server Daemon.
(9)检查OpenLDAP状态
执行ldapsearch -x检查是否有如下输出
[root@localhost ~]# ldapsearch -x -b '' -s base'(objectclass=*)'
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: ALL
#
#
dn:
objectClass: top
objectClass: OpenLDAProotDSE
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
2、部署Saslauthd
(1)安装saslauthd服务
[root@localhost ~]# yum install -y cyrus-sasl
[root@localhost ~]# systemctl restart saslauthd.service
[root@localhost ~]# systemctl enable saslauthd.service
(2)测试ldapsearch搜索
微软Windows AD是否正常
如果能搜索到用户,说明openldap访问Windows AD正常
(3)配置sasl访问ad
编辑/etc/sysconfig/saslauthd
[root@localhost ~]# vim /etc/sysconfig/saslauthd
修改为下面两行
MECH=ldap
FLAGS="-O /etc/saslauthd2ad.conf"
然后新建一个 /etc/saslauthd2ad.conf ,写入下面内容
ldap_servers 为微软AD 域连接地址,
ldap_bind_dn 微软 AD 域 信息,本次使用管理员信息,生产环境可以新建一个账号,也是可以的,因为他们认证过程不需要管理员。
ldap_password 域内密码(本次使用管理员信息)
[root@localhost ~]# vim /etc/saslauthd2ad.conf
ldap_servers: ldap://192.168.110.253
ldap_search_base: DC=huawang,DC=com
ldap_timeout: 60
ldap_filter: sAMAccountName=%U
ldap_bind_dn: CN=Administrator,CN=Users,DC=huawang,DC=com
ldap_password: Windows AD域管理员密码
ldap_deref: never
ldap_restart: yes
ldap_scope: sub
ldap_use_sasl: no
ldap_start_tls: no
ldap_version: 3
ldap_auth_method: bind
重启saslauthd服务
[root@localhost ~]# systemctl restart saslauthd.service
使用testsaslauthd命令测试WindowsAD上的用户是否认证成功
[root@localhost ~]# testsaslauthd -u Administrator -p testAD
0: OK "Success."
#表示 已经能成功通过saslauthd进行认证
可进一步AD里面加用户、或改密码测试。需注意AD修改密码,老密码依然可用5分钟。如验证不通过检查 sasl的配置。
(4)配置openldap
配置openldap 使用Saslauthd
编辑 /etc/openldap/ldap.conf
[root@localhost ~]# vim /etc/openldap/ldap.conf
# 增加以下内容
TLS_REQCERT never
sasl-host localhost
sasl-secprops none
#这两行配置非常重要,是告诉openldap使用本机的sasl服务,
#看了好多文档,花费7天时间,反复踩坑才后发现很多文档没说需要加这两行,导致LDAP-的认证请求没发往AD :(
重启 openldap
systemctl restart slapd.service
新建 /etc/sasl2/slapd.conf
[root@localhost ~]# vim /etc/sasl2/slapd.conf
# 添加如下内容
mech_list: plain
pwcheck_method: saslauthd
saslauthd_path: /var/run/saslauthd/mux
最后重启saslauthd服务
[root@localhost ~]# systemctl restart saslauthd.service
验证openldap是否支持SASL
[root@localhost ~]# ldapsearch -x -H ldap://127.0.0.1 -ZZ -b "" -LLL -s base supportedSASLMechanisms
dn:
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: PLAIN
# 出现如上结果说明openldap已支持SASL认证
#在上面的AD示例中,首先检查saslauthd在连接到AD时将使用的DN和密码是否有效:
ldapsearch -x -H ldap://192.168.110.253/ \
-D cn=Administrator,cn=Users,DC=huawang,DC=com \
-w password \
-b '' \
-s base
检查用户是否可以绑定到AD:
ldapsearch -x -H ldap://192.168.110.253/ \
-D cn=Administrator,cn=Users,DC=huawang,DC=com \
-w password \
-b cn=Users,DC=huawang,DC=com \
-s base \
"(objectclass=*)"
3、安装phpldapadmin
phpldapadmin提供了使用web页面管理OpenLDAP的方式,可直接安装,或Docker容器安装,
vim docker-compose.yaml
# dcoker-compose up -d
version: '3'
services:
phpldapadmin:
image: osixia/phpldapadmin
container_name: phpldapadmin252
hostname: phpldapadmin
restart: always
ports:
- "8001:80"
environment:
- PHPLDAPADMIN_HTTPS=false
- PHPLDAPADMIN_LDAP_HOSTS=192.168.110.252
(5)登录验证
使用浏览器登录phpldapadmin
http://192.168.110.x:8081
页面输入管理员的DN和密码即可登录
4、测试OpenLDAP使用AD密码进行认证
创建一个测试用户导入文件testuser.ldif
[root@localhost ~]# vim testuser.ldif
写入以下内容
dn: uid=ruijie,ou=people,dc=huawang,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
uid: ruijie
cn: ruijie
sn: ruijie
userpassword: {SASL}ruijie
givenname: ruijie
mail: ruijie@huawang.com
dn: uid=jhqinzicheng,ou=people,dc=huawang,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
uid: jhqinzicheng
cn: jhqinzicheng
sn: jhqinzicheng
userpassword: {SASL}jhqinzicheng
givenname: jhqinzicheng
mail: jhqinzicheng@huawang.com
导入测试用户
[root@localhost ~]# ldapadd -x -D "cn=Manager,dc=huawang,dc=com" -W -f testuser.ldif
Enter LDAP Password:
adding new entry "uid=ruijie,ou=people,dc=huawang,dc=com"
使用命令测试
[root@localhost ~]# ldapsearch -w ruijie -H ldap://127.0.0.1 -D "cn=ruijie,dc=huawang,dc=com" -b "dc=huawang,dc=com"
ldapwhoami -x -D uid=ruijie,ou=People,dc=test,dc=winad,dc=com -w a542129333A
dn:uid=ruijie,ou=People,dc=lework,dc=com
ldapsearch -w ruijie -H ldap://127.0.0.1 -D "uid=ruijie,ou=People,dc=test,dc=winad,dc=com" -b "uid=ruijie,ou=People,dc=test,dc=winad,dc=com"
这个测试命令,testuser用户在openldap和Windows AD上都存在,IP是本机openldap的IP,DN,查询DN也都是openldap的信息,但是密码却是在windows AD上管理的。如成功,到windows AD上修改用户密码,用新密码验证,再等5分钟,旧密码失效。到此配置完成
文章来源:
https://blog.csdn.net/shion0305/article/details/114934202
https://lework.github.io/2019/07/25/openldap-pass-through-ad/
停留在世界边缘,与之惜别