LDAP(Lightweight Directory Access Protocol)
轻量目录访问协议,他是基于 目录访问协议 X.500
的DAP发展过来的,Linux 程序名称为 slapd(stand-alone LDAP daemon)
。与LDAP一样提供类似的目录服务软件还有 ApacheDS
、Active Directory
、Red Hat Directory Service
。
LDAP的特点
- LDAP 基于 TCP/IP
- LDAP 的结构用树来表示
- LDAP 读快写慢
- Client/server 模型,Server 用于存储数据,Client提供操作目录信息树的工具,LDIF格式
- LDAP 是一种开放 Internet 标准,LDAP 协议是跨平台的 Interent 协议
术语
- 目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
- Entry:条目,也叫记录项,是LDAP中最基本的颗粒,就像字典中的词条,或者是数据库中的记录。通常对LDAP的添加、删除、更改、检索都是以条目为基本对象的。
- ObjectClass:对象类是属性的集合,LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。
- Attribute:每个条目都可以有很多属性(Attribute),比如常见的人都有姓名、地址、电话等属性。每个属性都有名称及对应的值,属性值可以有单个、多个,比如你有多个邮箱。
- Schema:对象类(ObjectClass)、属性类型(AttributeType)、语法(Syntax)分别约定了条目、属性、值,他们之间的关系如下图所示。所以这些构成了模式(Schema)——对象类的集合。条目数据在导入时通常需要接受模式检查,它确保了目录中所有的条目数据结构都是一致的。一般存放路径为/etc/openldap/schema,一个条目的属性必须存在于已定义的schema中
- LDIF(LDAP Data Interchange Format):LDIF 是一种普遍使用的文件格式,用来描述目录信息或可对目录执行的修改操作。
- dc(Domain Component):域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)
- o(Organization):组织-公司
- ou(Organization Unit):组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织)
- c(Country Name):国家
- cn(Common Name):常用名称,如“Thomas Johansson”(一条记录的名称)
- dc(Domain Component):域名
- sn(Surname):姓,如“谢”
- rdn(Relative dn):相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn=Thomas Johansson”
- uid(User Id):用户ID xianbin.xie(一条记录的ID)
- dn(Distinguished Name):“uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一)
- olc:on-line configuration 在线配置
- olcAccess: acl访问控制列表
目录树示例
+-------------+
| |
| dc=CN <---+ 顶 级 域 名
| |
+------+------+
|
|
+------v------+
| <---------+下 一 级 域 名
|dc=xiexianbin+-----------+
| | |
+-----+-------+ |
| |
| |
+-----v------+ +-----v------+
| | | |
+----------+ ou=Tech | | ou=Finance <-----+ 组 织
| | | | |
| +------+-----+ +-----+------+
| | |
| | |
+-----v-----+ +------v-----+ +-----v------+
| | | | | |
| ou=Web | | ou=App | | uid=abc <-----+ 对 象
| | | | | |
+-----+-----+ +------+-----+ +------------+
| |
| |
+-----v-----+ +------v-----+
| | | |
| uid=foo | | uid=bar |
| | | |
+-----------+ +------------+
DN 示例:
- dn:dc=xiexianbin,dc=CN
- dn:ou=Tech,dc=xiexianbin,dc=CN
- dn:uid=foo,ou=Web,ou=Tech,dc=xiexianbin,dc=CN
DN 规则:
- DN 的写法是从下向上,用逗号间隔
- DN 是唯一的,否则就没法确定一条entry了
- rdn 就是 DN 最左边的 entry
Docker 启动
docker run --detach --rm --name openldap \
--network my-network \
--env LDAP_ADMIN_USERNAME=admin \
--env LDAP_ADMIN_PASSWORD=adminpassword \
--env LDAP_USERS=customuser \
--env LDAP_PASSWORDS=custompassword \
bitnami/openldap:latest
LDAP 服务端
安装前需要关闭 SELINUX
安装
$ yum install openldap openldap-servers
# 版本:
$ slapd -V
@(#) $OpenLDAP: slapd 2.4.44 (Aug 4 2017 14:23:27) $
mockbuild@c1bm.rdu2.centos.org:/builddir/build/BUILD/openldap-2.4.44/openldap-2.4.44/servers/slapd
yum install -y db4 db4-utils
openldap
使用 Berkeley DB
存储数据。
配置结构
# tree /etc/openldap -L 1
/etc/openldap
├── certs # 存放TLS认证的CA证书等
├── check_password.conf # 密码校检配置
├── ldap.conf # openldap client 的配置文件
├── schema
└── slapd.d
├── cn=config # 存放数据库的配置文件
│ ├── cn=schema # 存放.ldif文件
│ ├── cn=schema.ldif
│ ├── olcDatabase={0}config.ldif
│ ├── olcDatabase={-1}frontend.ldif
│ ├── olcDatabase={1}monitor.ldif
│ └── olcDatabase={2}hdb.ldif
└── cn=config.ldif
生成证书
$ openssl req -new -x509 -nodes -out /etc/openldap/certs/cert.pem -keyout /etc/openldap/certs/priv.pem -days 365
管理员密码、DN和监控
slappasswd -s 123123 # 输入2次,示例密码为:123123,这个密码是动态的,每次生成都不一样
{SSHA}pHDo26ZYkXQFbmFQHPdBLV7aHSP7JTIz
vim /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
修改:
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
为:
olcSuffix: dc=xiexianbin,dc=cn
olcRootDN: cn=Manager,dc=xiexianbin,dc=cn
olcRootPW: {SSHA}pHDo26ZYkXQFbmFQHPdBLV7aHSP7JTIz # 新增密码
vim /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif
修改:
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth" read by dn.base="cn=Manager,dc=my-domain,dc=com" read by * none
为:
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth" read by dn.base="cn=Manager,dc=xiexianbin,dc=cn" read by * none
LDAPPW="123123"
SSHAPW=`slappasswd -s $LDAPPW`
sed -i '/olcRootPW: /d' /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
echo olcRootPW: $SSHAPW >> /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
sed -i 's/dc=my-domain,dc=com/'dc=xiexianbin,dc=cn'/g' /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
sed -i 's/dc=my-domain,dc=com/'dc=xiexianbin,dc=cn'/g' /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif
设置 Database Cache
OpenLDAP
默认使用的数据库是 BerkeleyDB
,现在来开始配置OpenLDAP数据库,使用如下命令:
$ cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
$ chown ldap:ldap -R /var/lib/ldap
$ chmod 700 -R /var/lib/ldap
$ ll /var/lib/ldap/
total 348
-rwx------. 1 ldap ldap 2048 Jul 18 14:01 alock
-rwx------. 1 ldap ldap 286720 Jul 18 14:01 __db.001
-rwx------. 1 ldap ldap 32768 Jul 18 14:01 __db.002
-rwx------. 1 ldap ldap 49152 Jul 18 14:01 __db.003
-rwx------. 1 ldap ldap 845 Jul 18 14:16 DB_CONFIG
-rwx------. 1 ldap ldap 8192 Jul 18 14:01 dn2id.bdb
-rwx------. 1 ldap ldap 32768 Jul 18 14:01 id2entry.bdb
-rwx------. 1 ldap ldap 10485760 Jul 18 14:01 log.0000000001
测试配置文件
# slaptest -u
6131c671 ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={1}monitor.ldif"
config file testing succeeded
启动服务
systemctl enable slapd
systemctl start slapd
systemctl status slapd
配置 LDIF
添加 cosine
、nis
和inetorgperson
模块到slapd服务程序
LDIF(LDAP Data Interchanged Format)
格式来保存条目,在 /etc/openldap/schema/
中,数据文件格式为 .ldif
,模板文件格式为 .schema
。
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
# 或添加全部 ldif 命令
ls /etc/openldap/schema/*.ldif | xargs -I {} sudo ldapadd -Y EXTERNAL -H ldapi:/// -f {}
systemctl restart slapd.service
填加根域条目
在/etc/openldap/
目录下,创建一个base.ldif
:
cat > /etc/openldap/base.ldif << EOF
dn: dc=xiexianbin,dc=cn
o: Manager
objectclass: dcObject
objectclass: organization
EOF
执行:
# ldapadd -f /etc/openldap/base.ldif -x -D cn=Manager,dc=xiexianbin,dc=cn -W
Enter LDAP Password:
adding new entry "dc=xiexianbin,dc=cn"
- -f 指定
ldif
文件 - -x 简单用户认证
- -D 绑定的 dn
- -W 提示输入绑定 dn 的密码
说明:以上命令解决 phpldapadmin
左侧 This base cannot be created with PLA
导入用户组
group.ldif
内容:
cat > /etc/openldap/group.ldif << EOF
dn: ou=Dev,dc=xiexianbin,dc=cn
ou: Dev
objectClass: top
objectClass: organizationalUnit
dn: ou=Web,dc=xiexianbin,dc=cn
ou: Web
objectClass: top
objectClass: organizationalUnit
EOF
# ldapadd -f /etc/openldap/group.ldif -x -D cn=Manager,dc=xiexianbin,dc=cn -W
Enter LDAP Password:
adding new entry "ou=Dev,dc=xiexianbin,dc=cn"
adding new entry "ou=Web,dc=xiexianbin,dc=cn"
cat > /etc/openldap/user.ldif << EOF
dn: sn=dev1,ou=Dev,dc=xiexianbin,dc=cn
cn: xie
sn: dev1
userPassword: 123123
telephoneNumber: 16666666666
email: xiedev1@xiexianbin.cn
description: "des"
olcAllows: ture
objectClass: person
dn: sn=web1,ou=Web,dc=xiexianbin,dc=cn
cn: xie
sn: web1
userPassword: 123123
telephoneNumber: 16666666666
email: xieweb1@xiexianbin.cn
description: "des"
olcAllows: ture
objectClass: person
EOF
ldapadd -f /etc/openldap/user.ldif -x -D cn=Manager,dc=xiexianbin,dc=cn -W
Enter LDAP Password:
adding new entry "sn=dev1,ou=Dev,dc=xiexianbin,dc=cn"
adding new entry "sn=web1,ou=Web,dc=xiexianbin,dc=cn"
进程介绍
OpenLDAP 包在服务器上安装了很多程序:
- 守护进程:
- slapd:主 LDAP 服务器
- slurpd:负责与复制 LDAP 服务器保持同步的服务器
- nslcd:Daemon for NSS and PAM lookups using LDAP
- 对网络上的目录进行操作的客户机程序。下面这两个程序是一对儿:
- ldapadd:打开一个到 LDAP 服务器的连接,绑定、修改或增加条目
- ldapsearch:打开一个到 LDAP 服务器的连接,绑定并使用指定的参数进行搜索
- 对本地系统上的数据库进行操作的几个程序:
- slapadd:将以 LDAP 目录交换格式(LDIF)指定的条目添加到 LDAP 数据库中
- slapcat:打开 LDAP 数据库,并将对应的条目输出为 LDIF 格式
命令行工具:
# ls /usr/bin/ | grep ldap
ldapadd
ldapcompare
ldapdelete
ldapexop
ldapmodify
ldapmodrdn
ldappasswd
ldapsearch
ldapurl
ldapwhoami
LDAP client
$ ldapsearch -x -b "dc=xiexianbin,dc=cn" -H ldap://127.0.0.1
# extended LDIF
#
# LDAPv3
# base <dc=xiexianbin,dc=cn> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# xiexianbin.cn
dn: dc=xiexianbin,dc=cn
o:: eGlleGlhbmJpbiA=
objectClass: dcObject
objectClass: organization
dc: xiexianbin
# Dev, xiexianbin.cn
dn: ou=Dev,dc=xiexianbin,dc=cn
ou: Dev
objectClass: top
objectClass: organizationalUnit
# Web, xiexianbin.cn
dn: ou=Web,dc=xiexianbin,dc=cn
ou: Web
objectClass: top
objectClass: organizationalUnit
# search result
search: 2
result: 0 Success
# numResponses: 4
# numEntries: 3
LDAP 客户端
- 用户 PAM 认证: ssh login -> PAM -> SSSD -> LDAP ?
- 用户名称解析: NSS -> nslcd.service -> LDAP
安装
# 安装包
yum install -y openldap-clients nss-pam-ldapd
# 先禁用 ldap 和 sssd
authconfig --disableldap --disablesssd --update
# 启动服务
systemctl restart nslcd.service
authconfig --enableldap --enableldapauth --disablesssd --disablesssdauth --enableforcelegacy --ldapserver=<ldap-server-ip> --ldapbasedn="dc=xiexianbin,dc=cn" --enablemkhomedir --update
# 重启服务
systemctl restart nslcd.service
systemctl enable nslcd.service
systemctl disable sssd
systemctl stop sssd
$ cat /etc/nslcd.conf | grep ^[^#]
uid nslcd
gid ldap
uri ldap://sms1/ ldap://sms2/
base dc=xiexianbin,dc=cn
ssl no
tls_cacertdir /etc/openldap/cacerts
$ cat /etc/nsswitch.conf | grep ^[^#]
passwd: files ldap
shadow: files ldap
group: files ldap
hosts: files dns myhostname
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
netgroup: files ldap
publickey: nisplus
automount: files ldap
aliases: files nisplus
$ cat /etc/pam.d/system-auth | grep ldap
auth sufficient pam_ldap.so use_first_pass
account [default=bad success=ok user_unknown=ignore] pam_ldap.so
password sufficient pam_ldap.so use_authtok
session optional pam_ldap.so
# 还有如下文件
/etc/pam.d/fingerprint-auth
/etc/pam.d/password-auth
/etc/pam.d/postlogin
/etc/pam.d/screen
/etc/pam.d/smartcard-auth
/etc/pam.d/smtp
查看 passwd/group
正常情况下,我们通过 /etc/passwd
、/etc/group
查看 Linux 机器的 user 和 group 信息,对接 LDAP 后,我们需要通过如下命令获取:
getent passwd
getent group
备份与还原
# 备份
ldapsearch -x -b 'dc=xiexianbin,dc=cn' >> backup.ldif
# 导入
ldapadd -H ldap://127.0.0.1 -x -D "dc=xiexianbin,dc=cn" -f backup.ldif -w <password>
管理工具
phpldapadmin
yum install phpldapadmin php httpd -y
相关配置文件:
- /etc/httpd/conf.d/phpldapadmin.conf # httpd 配置
- /usr/share/phpldapadmin/ # phpldapadmin 目录
- /etc/phpldapadmin/config.php # phpldapadmin 配置文件
修改 /etc/phpldapadmin/config.php
,找到Define your LDAP servers in this section
,去掉注释:
$servers->setValue('server','host','127.0.0.1');
$servers->setValue('server','port',389);
$servers->setValue('server','base',array('dc=xiexianbin,dc=cn')); # 有修改,在array中输入设置的olcSuffix
$servers->setValue('login','auth_type','session');
//$servers->setValue('login','attr','uid');
修改权限vim /etc/httpd/conf.d/phpldapadmin.conf
:
Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs
<Directory /usr/share/phpldapadmin/htdocs>
<IfModule mod_authz_core.c>
# Apache 2.4
Require local
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from ::1
</IfModule>
</Directory>
为:
Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs
<Directory /usr/share/phpldapadmin/htdocs>
<IfModule mod_authz_core.c>
# Apache 2.4
Require local
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order Deny,Allow
# Deny from all
Allow from all
</IfModule>
</Directory>
[root@xiexianbin_cn ~]# getsebool httpd_can_connect_ldap
httpd_can_connect_ldap --> off
[root@xiexianbin_cn ~]# setsebool -P httpd_can_connect_ldap on
[root@xiexianbin_cn ~]# getsebool httpd_can_connect_ldap
httpd_can_connect_ldap --> on
systemctl start httpd
访问:
- http://:/phpldapadmin
- http://:/ldapadmin
使用 olcRootDN
和 olcRootPW
登陆:
- 用户名:cn=Manager,dc=xiexianbin,dc=cn
- 密码
ldap-utils 工具
sudo apt install ldap-utils
$ ldapsearch -x -W \
-H ldap://ldap.example.org \
-b 'dc=example,dc=org' "(&(objectClass=user)(sAMAccountName=xiexianbin))" \
-D "<DOMAIN | dc>\xiexianbin"
# xxx, Users, xiexianbin.cn
dn:: CN=谢先斌,CN=Users,DC=xiexianbin,DC=cn
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn:: 6LCi5YWI5paM # 谢先斌
sn:: 6LCi
givenName:: 5YWI5paM # 先斌
distinguishedName:: CN=谢先斌,CN=Users,DC=xiexianbin,DC=cn
instanceType: 4
whenCreated: 19911900181000.0Z
whenChanged: 19911900181000.0Z
displayName:: 6LCi5YWI5paM # 谢先斌
uSNCreated: 758527
memberOf: CN=admin,CN=Users,DC=xiexianbin,DC=cn
uSNChanged: 999
name:: 6LCi5YWI5paM # 谢先斌
objectGUID:: xx==
userAccountControl: 1024
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime:
lastLogoff: 0
lastLogon:
pwdLastSet:
primaryGroupID:
objectSid::
accountExpires:
logonCount:
sAMAccountName: xiexianbin
sAMAccountType:
userPrincipalName: xiexianbin@xiexianbin.cn
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=xiexianbin,DC=cn
dSCorePropagationData:
lastLogonTimestamp:
mail: xiexianbin@xiexianbin.cn
扩展