1. 目录服务

目录服务更多地是一个为快速查询而优化过的数据库,也支持更新

LDAP目录结构为树型,现在更流行按dns域来划分组织架构

每个节点可以视为一个entry,该entry拥有哪些属性,是由其所归属的objectClass来决定的,objectClass本身也是一个特殊的属性

schema文件中定义有哪些objectClass

RDN指定相对路径,如ou=People,dc=ben,dc=com

DN指绝对路径,如uid=babs,ou=People,dc=ben,dc=com

一个entry通过它的DN来引用

可以像关系型数据库一样,在某个范围内(dc=ben,dc=com)查询某个entry的某些属性,指定filter过滤器

LDAPv3是一个协议,openldap是它的一个实现,slapd是其二进制启动文件

1.2 slapd特点:
  1. CS架构
  2. 支持sasl认证
  3. 支持tls
  4. acl
  5. 多个backend db;当前使用的是LMDB
  6. 线程池
  7. 多节点目录内容复制
  8. 代理缓存
  9. 可定制性强

apache ds网站上说,openldap原来使用 BDB as their default database,这样会破坏数据,后来openldap换成了LMDB才解决,而apache ds还没有解决,所以不建议生产环境使用

服务端口389,tls加密用636

2. 安装openldap

安装后用slapd -VVV查看具体信息

2.1 编译

编译注意事项

# --enable-wrappers
# 文档上说tcp_wrapper在阻止连接时开销较大,


# 这个选项需要libevent 2.1 or later
--enable-balancer \

# 不能在build目录下make
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
yum install cyrus-sasl-devel libtool-ltdl-devel -y
 
PREFIX_DIR=/opt/openldap
mkdir -p ${PREFIX_DIR}
./configure \
--with-cyrus-sasl \
--enable-modules \
--enable-memberof \
--enable-refint \
--prefix=${PREFIX_DIR}

# 在enable-modules后,还需要启用具体的模块,如
--enable-memberof
--enable-refint
# 而且编译后用slapd -VVV查看,看到还是编译成了静态的
@(#) $OpenLDAP: slapd 2.5.14 (Apr 19 2024 09:42:35) $
    root@c84:/usr/local/src/openldap-2.5.14/servers/slapd

Included static overlays:
    memberof
    refint
    syncprov
Included static backends:
    config
    ldif
    monitor
    mdb
    relay
  • 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.

编译后

bin下是ldap客户端命令

sbin下slap服务端命令

libexec下是服务启动命令slapd

echo 'export PATH=$PATH:'${PREFIX_DIR}/bin:${PREFIX_DIR}/sbin:${PREFIX_DIR}/libexec > /etc/profile.d/openldap.sh
. /etc/profile.d/openldap.sh
echo "${PREFIX_DIR}/lib" > /etc/ld.so.conf.d/openldap.conf
ldconfig
ln -s ${PREFIX_DIR}/include /usr/include/openldap
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
2.2 yum安装
yum install openldap-servers openldap-clients
  • 1.

会在/usr/lib64/openldap/下有module和库文件,可以在ldif文件中通过olcModuleload: memberof.la加载

2.3 docker

编写了官方镜像osixia的docker-compose文件,但目前版本是2.4.47,3年没更新了

2.4 yum install openldap-ltb
/usr/local/openldap/sbin/slapd-cli status
  • 1.
searchbase='cn=schema,cn=config'
ldapsearch -x -D 'cn=config' -H ldap://localhost -b "$searchbase" -A -LLL -w secret
ldapsearch -Q -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi -b "$searchbase" -A -LLL
  • 1.
  • 2.
  • 3.
# 查看加载了哪些模块
ldapsearch -Q -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi -b "$searchbase" "(cn=module*)"
  • 1.
  • 2.
# 查看man ldapsearch,看到最后可以指定要查询的属性,+表示所有可以操作的属性
ldapsearch -Q -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi -b "dc=ben,dc=com" "(uid=ldapuser3)" -LLL +
  • 1.
  • 2.
# 删除olcOverlay
cat > bak/del.ldif <<EOF
dn: olcOverlay={6}refint,olcDatabase={1}mdb,cn=config
changetype: delete
EOF

ldapmodify -Q -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi -f bak/del.ldif
# 可以man ldapmodify查看帮助,有针对单个dn进行多次修改的写法

# 针对ldapadd overlay的操作,再用ldapdelete去删除,一直报错invalid DN ==== 耐心解决
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
2.5 启动
systemctl enable --now slapd

# systemctl cat slapd,看到
ExecStart=/usr/sbin/slapd -u ldap -h "ldap:/// ldaps:/// ldapi:///"
  • 1.
  • 2.
  • 3.
  • 4.

可以man slapd查看其对-f(默认配置文件)和-F(默认启动目录)的说明

有2种启动方式:

  1. 先修改完slapd.ldif后,再slapadd生成目录,再启动
# 创建slapd-config-directory,该目录所有者要和启动slapd进程的用户相同,当前为"ldap";还要注意权限
slapd_config_directory=
su - ldap -c "mkdir -pm 750 ${slapd_config_directory}" -s /bin/bash
# 修改完slapd.ldif后(修改olcSuffix、olcRootDN和olcRootPW等),生成config数据库
# -n 0表示数据库序号,0表示config库
slapadd -n 0 -l slapd.ldif -F ${slapd_config_directory}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  1. 先启动,再用ldapadd/ldapmodify修改(使用这种方式)

3. 配置文件

3.1 schema

schema文件中定义有哪些objectClass,文件中也有类似SNMP 的OID这样的数字层级

schema文件位于/etc/openldap/schema目录中,该目录中同时有.schema和.ldif 两类文件

.schema文件用于在slapd.ldif中include

.ldif文件用于服务运行后,再ldapadd

3.2 slapd.ldif

2.4版本后使用slapd.ldif

ldif格式的文件,内容格式有严格要求,以空行分隔entry,每行尾不能有空白字符

配置文件中的指令

# 查看该searchbase有哪些属性
# 其中-A选项只显示属性名,不显示值,可以过滤很多内容
# -LLL选项可以指定输出格式中是否包含注释,ldif版本等
searchbase='cn=schema,cn=config'
ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b "$searchbase" -A -LLL 

# 查询具体属性,在属性后面加"+" 
ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcRootDN=*)" dn olcRootDN olcRootPW -LLL
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  1. cn=config部分
dn: cn=config
objectClass: olcGlobal
cn: config
olcIdleTimeout: 30
olcLogLevel: Stats
olcReferral: ldap://root.openldap.org
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  1. cn=module,cn=config
  2. cn=schema,cn=config;实际的schema定义已经被硬编码到slapd二进制文件中了
    自定义schema时用
  3. frontend是一个特殊的database,它用来存放database-level选项,这些选项(如olcAccess)会被应用到其他所有database;其他database的配置也能覆盖这个全局配置
    config也是一个特殊的database
    config和frontend databases总是先于其他databases创建,即使没有显式定义也会创建
  4. olcDatabase={1}mdb,cn=config
olcAccess	# olcAccess指令定义ACL,若不定义,默认匿名用户也有只读权限
olcRootDN:	# 该条目可以不存在于该database,所以同一个rootDN可以管理多个不同suffix的database
olcSyncrepl
olcTimeLimit: 3600
olcSizeLimit: 500
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
3.3 初始化mdb

该段虽然从官方文档中查到,但现在又查不到了,没时间不用管

openldap的根目录可以先进行初始化,也可以不用,只要slapd.ldif文件中定义了olcRootDN和olcRootPW

文档上说为了避免一个先有鸡还是先有蛋的问题,不初始化也能连接

初始化就是添加base.ldif,创建dn: cn=admin,dc=ben,dc=com

4. 命令

4.1 客户端命令

客户端命令属于在线式,其所做的修改立即生效

ldapsearch

ldapmodify,ldapadd在功能上相当于ldapmodify -a

ldapdelete

ldapwhoami ldapwhoami -H ldap://:389/ -D 'banqianwanbi@choice.com' -w,AD服务器注意-D写法

选项:

-x # 指定simple认证,需要输入密码,默认为sasl认证;使用简单认证会暴露明文密码

-D # 指定绑定的DN

-H # 指定连接的主机url

-b # 指定searchbase,必须指定,没有默认值

-A # 只显示属性名,不显示值

-LLL # 指定显示信息的详细程序

-c # 出错继续,不退出

-n # dry run

执行报错时,查看日志

4.2 离线式

直接修改数据库,没怎么用过

slapadd

slapcat

slapindex

5. 访问控制

olcAccess指令格式

olcAccess:access to [what] by [who] [control]

当没有显式定义olcAccess时,acl list 为空,此时会追加默认全局只读权限

否则,acl list非空,此时会追加全局无任何权限(access to * by * none)

当使用ldapsearch查看olcAccess时,有多条acl,会用{0}、{1}这样的序号来表示,若要修改,也需要指定具体的序号

6. tls

6.1 服务端

需要定义这几个:

olcTLSCACertificateFile: olcTLSCertificateFile: olcTLSCertificateKeyFile:

6.2 客户端

不管是使用ldapsearch等命令行,还是linux主机通过ldap账户登录,都需要信任(为服务端签发证书的)CA证书,并在配置文件中指定证书路径;或者用tls_reqcert never/allow

使用ldapsearch等命令行

在linux主机的/etc/openldap/ldap.conf文件中添加

TLS_CACERT /path/to/ca.crt	# 然后在指定路径下存放CA的证书
TLS_REQCERT never
  • 1.
  • 2.

linux主机通过ldap账户登录

# /etc/nslcd.conf文件中添加tls_cacertdir行或tls_cacertfile行,并关闭start_tls
tls_cacertdir /etc/openldap/cacerts
tls_reqcert never
  • 1.
  • 2.
  • 3.

此时GUI中Apache DS Studio可以连接

Apache DS Studio在修改时,会有操作日志

定义密码策略、密码审计、使用ldap集中管理sudo权限

##

x. 客户端接入

yum install openldap后会有/etc/openldap/ldap.conf

可以在其中配置默认的ldap server信息,这样就不用在命令行中输入

也可以用其他配置文件,如.ldaprc,具体man ldap.conf

x.1 先集中创建用户账号
# 依赖openldap-clients和openldap-servers,会自动安装
yum install migrationtools
  • 1.
  • 2.
# 安装完后,查看脚本
ll /usr/share/migrationtools

export DEFAULT_BASE="dc=ben,dc=com"

# 生成base OU
/usr/share/migrationtools/migrate_base.pl > ou_base.ldif

# 添加OU
ldapadd -f ou_base.ldif 

# 生成用户ldif文件
/usr/share/migrationtools/migrate_passwd.pl /etc/passwd user.ldif

# 生成组ldif文件
/usr/share/migrationtools/migrate_group.pl /etc/group group.ldif

# 先导入2个schema
ldapadd -Y EXTERNAL -H ldapi:/// -f schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f schema/nis.ldif

# 然后才能导入user和group ldif
ldapadd -x -D 'cn=admin,dc=ben,dc=com' -W -f /tmp/04/user.ldif -c
ldapadd -x -D 'cn=admin,dc=ben,dc=com' -W -f /tmp/04/group.ldif -c
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
x.2 linux服务器
yum install oddjob-mkhomedir authconfig nss-pam-ldapd
  • 1.
# /etc/nslcd.conf文件中添加tls_cacertdir行或tls_cacertfile行
authconfig \
	--enablemkhomedir \
	--enableldaptls \
	--enableldap \
	--enableldapauth \
	--ldapserver=ldaps://ldap1.ben.host \
	--ldapbasedn='dc=ben,dc=com' \
	--update
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

原来centos7上可以直接认证成功(通过yum安装,自定义的olcAccess),

后来使用docker安装又试,开始失败了;应该是这条“by self read”导致不能直接认证,需要验证一个账户权限后再读取dc=ben,dc=com的条目,才开始登录用户认证

olcAccess: {1}to * by dn="uid=ldap,ou=People,dc=ben,dc=com" read by dn="cn=adm
 in,dc=ben,dc=com" write by self read
  • 1.
  • 2.

这时在/etc/nslcd.conf文件中添加bind认证信息,再用systemctl restart nslcd重启服务后可以了

binddn cn=readonly,dc=ben,dc=com
bindpw readonly
  • 1.
  • 2.

centos8系统接入时, 参考,会自动创建家目录

在/etc/sssd/sssd.conf文件中添加bind认证信息,再用systemctl restart sssd oddjobd重启服务后可以了

ldap_default_bind_dn = uid=ldap,ou=People,dc=ben,dc=com
# 验证方式,默认为password
ldap_default_authtok_type = password
ldap_default_authtok = hello
  • 1.
  • 2.
  • 3.
  • 4.
x.3 vsftpd

首先需要vsftpd服务器本身先作为linux服务器接入,然后在user_conf目录下创建对应的用户信息,此时可以通过在FTP_ROOT下手动创建用户家目录,或者直接将FTP_ROOT设置为/home,然后自动创建家目录,并通过autofs自动挂载

y. web-ui客户端

y.1 ssp

在官网上有详细文件,编写了docker-compose启动文件,可以自助修改密码

容器可以直接使用宿主机的dns解析

z. 启用memberOf

  1. 加载memberof和refint模块
  2. 添加2个overlay
  3. 使用迁移工具生成的group.ldif中,posixGroup中有属性memberUid来定义组成员,但没有member属性
  4. 目前决定ou=Group专门用来存储posixGroup组,用于linux操作系统登录;其他应用系统再创建dn: ou=app_group,dc=ben,dc=com,用来存放objectClass: groupOfNames类型的组,供其他应用登录
    jenkins和pve中,指定通过memberOf属性来查询用户的组信息,用户登录成功后,能看到组信息,然后再对组进行授权

    gitea中,虽然界面显示通过memberUid来在组中查询包含的用户信息,也有通过将ldap中组映射成gitea的组织和团队,但都不生效


未完成的部分

6. 备份

  1. mdb_copy命令
  2. slapcat命令
    slapcat -F slapd.d -n0 -l extracted_config.ldif
    slapcat -f slapd.conf -b "dc=example,dc=com"

还原时再使用slapadd命令

# 也可以用slapcat命令备份出来,修改后再用上面slapadd命令导入
slapcat -F slapd.d -n0 -l extracted_config.ldif
  • 1.
  • 2.

使用yum install openldap-ltb安装后,带有slapd-cli.sh脚本,可以执行多种任务,包括备份、还原