OpenLDAP 轻型目录访问协议
参考:
LDAP 全称轻量级目录访问协议(英文:Lightweight Directory Access Protocol),从X.500目录访问协议的基础上发展过来的,是一个运行在 TCP/IP 上的目录访问协议。
基础概念
Entry 条目 --> Schema 模式 --> ObjectClass 对象类 --> Attribute 属性
Entry
LDAP 中的信息按照目录信息树结构组织,树中的一个节点称之为条目(Entry),条目包含了该节点的属性及属性值。
- dn:条目的唯一标识,例如:
cn=root,dc=example,dc=com
- rdn:区别名,一般指 dn 最左边的部分,例如:
cn=root
。它与RootDN
不同,RootDN
通常与RootPW
同时出现,特指管理 LDAP 中信息的最高权限用户 - Base DN:LDAP目录树的最顶部就是根,例如:
dc=example,dc=com
Schema
模式是ObjectClass
对象类的集合。
例如:/etc/ldap/schema/inetorgperson.ldif
定义了ObjectClass: inetOrgPerson
ObjectClass
对象类是Attribute
属性的集合,它定义了一套属性的规则。
例如:ObjectClass: inetOrgPerson
定义了employeeNumber
Attribute
每个条目可以有很多属性(Attribute),例如:姓名、地址、电话。
LDAP为人员组织机构中常见的对象都设计了属性:
属性 | 别名 | 描述 | 举例 |
---|---|---|---|
commonName | cn | 名称(姓名) | conanli |
surname | sn | 姓氏 | li |
organizationalUnitName | ou | 单位(部门)名称 | IT |
organization | o | 组织(公司)名称 | example |
telephoneNumber | 电话号码 | 110 | |
objectClass | 内置属性 | inetOrgPerson |
准备
机器名 | IP | 系统 | 内核 | 配置 | 计划安装的软件 |
---|---|---|---|---|---|
ldap-node1 | 192.168.56.103 | centos 7.5.1804 | linux 3.10.0 | 2 核 / 4G 内存 | openldap-servers-2.4.44 openldap-clients-2.4.44 phpldapadmin-1.2.3 keepalived-1.3.5 |
ldap-node2 | 192.168.56.104 | centos 7.5.1804 | linux 3.10.0 | 2 核 / 4G 内存 | openldap-servers-2.4.44 openldap-clients-2.4.44 phpldapadmin-1.2.3 keepalived-1.3.5 |
安装 OpenLDAP
在ldap-node1
执行以下内容:
yum install -y openldap-servers openldap-clients migrationtools
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown ldap:ldap /var/lib/ldap/DB_CONFIG
systemctl start slapd
systemctl enable slapd
修改顶级域
在ldap-node1
执行以下内容:
注意:cn=config
和olcDatabase={2}hdb
分别是/etc/openldap/slapd.d
和/etc/openldap/slapd.d/cn\=config
下的目录,请根据实际情况做调整
cat > chdomain.ldif <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com
EOF
ldapmodify -Y EXTERNAL -H ldapi:/// -f chdomain.ldif
配置管理员
在ldap-node1
执行以下内容:
RootPW=$(slappasswd -s 123456)
cat > chroot.ldif <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=root,dc=example,dc=com
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: $RootPW
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=root,dc=example,dc=com" read by * none
EOF
ldapmodify -Y EXTERNAL -H ldapi:/// -f chroot.ldif
导入内置 Schema
在ldap-node1
执行以下内容:
注意:ObjectClass
存在依赖关系,注意执行的先后顺序,具体依赖可以打开文件查看
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/misc.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/openldap.ldif
添加用户
在ldap-node1
执行以下内容:
cat > chuser.ldif <<EOF
dn: dc=example,dc=com
objectClass: top
objectClass: domain
dc: example
dn: cn=root,dc=example,dc=com
objectClass: organizationalRole
cn: root
dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people
dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: group
EOF
# -x 简单身份验证,-W 强制提示输入密码,-w 指定密码,-D RootDN 识别名,-f LDIF 文件
ldapadd -x -W -D "cn=root,dc=example,dc=com" -f chuser.ldif
ldapadd -x -w 123456 -D "cn=root,dc=example,dc=com" -f chuser.ldif
导入 MemberOf
部分第三方应用会依赖memberof
,可以提前安装,以备不时之需。
在ldap-node1
执行以下内容:
memberof
cat > memberof.ldif <<EOF
dn: cn=module{0},cn=config
cn: module
objectclass: olcModuleList
olcmoduleload: memberof.la
olcmodulepath: /usr/lib64/openldap
dn: olcOverlay={0}memberof,olcDatabase={2}hdb,cn=config
objectClass: olcConfig
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: top
olcOverlay: {0}memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
EOF
ldapadd -Y EXTERNAL -H ldapi:/// -f memberof.ldif
在ldap-node1
执行以下内容:
refint
cat > refint.ldif <<EOF
dn: cn=module{1},cn=config
cn: module
objectclass: olcModuleList
olcmoduleload: refint.la
olcmodulepath: /usr/lib64/openldap
dn: olcOverlay={1}refint,olcDatabase={2}hdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: {1}refint
olcRefintAttribute: memberof member manager owner
EOF
ldapadd -Y EXTERNAL -H ldapi:/// -f refint.ldif
testing
添加用户conanli
和分组it
,以检查部署是否正常
在ldap-node1
执行以下内容:
ConanLiPW=$(slappasswd -s 123456)
cat > add_user.ldif <<EOF
dn: uid=conanli,ou=people,dc=example,dc=com
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
uid: conanli
cn: ConanLi
sn: Li
givenName: Conan
mail:
uidNumber: 5000
gidNumber: 10000
loginShell: /bin/bash
userPassword: $ConanLiPW
homeDirectory: /home/conanli
EOF
ldapadd -x -w 123456 -D "cn=root,dc=example,dc=com" -f add_user.ldif
cat > add_group.ldif <<EOF
dn: cn=it,ou=group,dc=example,dc=com
objectClass: groupOfNames
cn: it
member: uid=conanli,ou=people,dc=example,dc=com
description: IT Department
EOF
ldapadd -x -w 123456 -D "cn=root,dc=example,dc=com" -f add_group.ldif
ldapsearch -x -LLL -H ldap:/// -b uid=conanli,ou=people,dc=example,dc=com dn memberof
查询
常用的数据查询,可以使用ldapsearch [options] [filter [attributes...]]
,options
如下:
参数 | 说明 |
---|---|
-H | ldapuri,格式为:,不能与 -h 和 -p 同时使用 |
-h | LDAP服务器IP,与 -p 可结合使用,不能与 -H 同时使用 |
-p | LDAP服务器端口号,与 -h 可结合使用,不能与 -H 同时使用 |
-x | 使用简单认证方式 |
-D | 所绑定的服务器的 DN |
-w | 绑定 DN 的密码,与 -W 二者选一 |
-W | 不输入密码,会交互式的提示用户输入密码,与 -w 二者选一 |
-f | 指定输入条件,在 RFC 4515 中有更详细的说明 |
-c | 出错后忽略当前错误继续执行,缺省情况下遇到错误即终止 |
-n | 模拟操作但并不实际执行,用于验证,常与 -v 一同使用进行问题定位 |
-v | 显示详细信息 |
-d | 显示 debug 信息,可设定级别 |
-s | 指定搜索范围, 可选值:base/one/sub/children |
ldapsearch -H ldap:/// -x -s base -b "" subschemaSubentry
ldapsearch -H ldap:/// -x -s base -b "cn=Subschema" objectClasses
# 根据 dn 查询
# 查询 RootDN 管理员
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "cn=root,dc=example,dc=com"
# 查询 people 分组,及其下的用户
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "ou=people,dc=example,dc=com"
# 查询 conanli 成员
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "uid=conanli,ou=people,dc=example,dc=com"
# 使用模糊匹配
# 查询所有分组
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "dc=example,dc=com" "ou=*"
# 根据 uid 查询
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "dc=example,dc=com" "uid=conanli"
# 返回指定信息
# 只返回 dn 和 cn 信息
ldapsearch -H ldap:/// -x -D "cn=root,dc=example,dc=com" -w 123456 -b "dc=example,dc=com" "uid=conanli" dn cn
# 验证用户密码
ldapsearch -H ldap:/// -x -D "uid=conanli,ou=people,dc=example,dc=com" -w 123456
安装 phpLDAPadmin
一个 Web 版的可视化工具。
在ldap-node1
执行以下内容:
yum install -y epel-release
yum install -y phpldapadmin
# 修改 phpLDAPadmin 配置
# 打开 $servers->setValue('login','attr','dn'),注释 $servers->setValue('login','attr','uid'),结果如下:
sed -n '397,398p' /etc/phpldapadmin/config.php
$servers->setValue('login','attr','dn');
// $servers->setValue('login','attr','uid');
# 修改 apache 配置
# 允许外网访问
sed -n '8,13p' /etc/httpd/conf.d/phpldapadmin.conf
<Directory /usr/share/phpldapadmin/htdocs>
<IfModule mod_authz_core.c>
# Apache 2.4
Require all granted
</IfModule>
</Directory>
# 开机启动
systemctl start httpd
systemctl enable httpd
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
phpLDAPAdmin-login
安装 LDAPadmin
phpLDAPAdmin-login双主复制
OpenLDAP 支持主主数据同步。
在ldap-node1
执行以下内容:
syncprov
cat > syncprov.ldif <<EOF
dn: cn=module{2},cn=config
cn: module
objectclass: olcModuleList
olcmoduleload: syncprov.la
olcmodulepath: /usr/lib64/openldap
dn: olcOverlay={2}syncprov,olcDatabase={2}hdb,cn=config
objectClass: olcConfig
objectClass: olcSyncProvConfig
objectClass: olcOverlayConfig
olcOverlay: {2}syncprov
olcSpSessionLog: 100
EOF
ldapadd -Y EXTERNAL -H ldapi:/// -f syncprov.ldif
syncrepl
以下为数据同步的具体,不同机器会有点不同,复制ldap-node1
,命名为ldap-node2
,然后在ldap-node1
执行以下内容:
cat > syncrepl1.ldif <<EOF
dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 1
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl:
rid=1
provider=ldap://192.168.56.104:389
binddn="cn=root,dc=example,dc=com"
bindmethod=simple
credentials=123456
searchbase="dc=example,dc=com"
type=refreshAndPersist
retry="5 5 300 5"
timeout=1
-
add: olcMirrorMode
olcMirrorMode: TRUE
EOF
ldapmodify -Y EXTERNAL -H ldapi:/// -f syncrepl1.ldif
在ldap-node2
执行以下内容:
cat > syncrepl2.ldif <<EOF
dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 2
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl:
rid=2
provider=ldap://192.168.56.103:389
binddn="cn=root,dc=example,dc=com"
bindmethod=simple
credentials=123456
searchbase="dc=example,dc=com"
type=refreshAndPersist
retry="5 5 300 5"
timeout=1
-
add: olcMirrorMode
olcMirrorMode: TRUE
EOF
ldapmodify -Y EXTERNAL -H ldapi:/// -f syncrepl2.ldif
testing
可以通过可视化工具连接到ldap-node1
,然后通过工具删除分组it
,最后再连接ldap-node2
检查是否也删除了。
Keepalived
Keepalived 可以通过IP漂移,实现服务的高可用,避免单点故障。
首先定一个向外提供服务的虚拟IP,例如:192.168.56.105
,具体方案如下:
当ldap-node1
的slapd
服务可用时,在ldap-node1
添加192.168.56.105
解析,否则在ldap-node2
添加,可以通过命令观察ip addr
路由的变化。
在ldap-node1
执行以下内容:
yum install -y keepalived
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id ldap-node1
}
vrrp_script check_slapd_status {
script "pidof slapd"
interval 3
weight -5
}
vrrp_instance VI_1 {
state MASTER
interface enp0s3
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.56.105
}
track_script {
check_slapd_status
}
}
EOF
systemctl restart keepalived
systemctl enable keepalived
在ldap-node2
执行以下内容:
yum install -y keepalived
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id ldap-node2
}
vrrp_script check_slapd_status {
script "pidof slapd"
interval 3
weight -5
}
vrrp_instance VI_1 {
state BACKUP
interface enp0s3
virtual_router_id 51
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.56.105
}
track_script {
check_slapd_status
}
}
EOF
systemctl restart keepalived
systemctl enable keepalived
testing
- 在
ldap-node1
执行systemctl stop slapd
关闭OpenLDAP
-
ldap-node2
上执行ip addr
,观察其中的变化 - 在浏览器上试试
http://192.168.56.105/ldapadmin
是否可以访问
注意:
-
vrrp_script
的定义必须放在vrrp_instance
前,否则无法执行 - 当
vrrp_script
的script
包含复杂的命令时,最好关闭selinux
,否则会调用失败,例如:systemctl