🗒️openldap的搭建和集成使用
2023-4-27
| 2023-5-6
0  |  0 分钟
type
status
date
slug
summary
tags
category
icon
password

1.使用ldap的目的

Devops流程通常涉及多个web工具,如果每个工具维护一套账号,大一点的项目会非常麻烦。ldap协议非常成熟(古早),故绝大部分平台工具支持此协议。
ldap和各平台集成使用的思路:ldap创建多个ou,在ou下新建用户,平台配置的搜索根指定需要的ou(当然你也可以用User search base 等配置缩小搜索范围),这样该ou下面的用户就有平台的登录权限。
notion image
如图所示,你需要让ou=acompany下面的用户都可以使用VPN,又只希望cn=ops,ou=acompany 下面的用户使用Jenkins。那你可以在VPN集成ldap时搜索根指定ou=acompany,dc=domain,dc=com ,而Jenkins集成ldap时搜索根指定cn=ops,ou=acompany,dc=domain,dc=com

2.ldap的基础概念

notion image
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”
以上这些类别没有指定特定的用法,这些完全由应用程序自行决定。

3.openLDAP的搭建-deployment

💡
默认已配置好deployment需要的环境
  • StorageClass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ldap namespace: tool annotations: storageclass.kubernetes.io/is-default-class: "true" #provisioner: fuseim.pri/ifs provisioner: nfs-client parameters: archiveOnDelete: "true"
  • ldap-all.yaml
## ldap deploy kind: Deployment apiVersion: apps/v1 metadata: name: ldap-server namespace: tool labels: app: ldap-server annotations: kubesphere.io/alias-name: LDAP kubesphere.io/description: 认证中心 spec: replicas: 1 selector: matchLabels: app: ldap-server template: metadata: labels: app: ldap-server spec: volumes: - name: volume-8aprj6 persistentVolumeClaim: claimName: ldap-config-pvc - name: volume-hj6df3 persistentVolumeClaim: claimName: ldap-data-pvc containers: - name: container-ad1z7z image: 'osixia/openldap:stable' ports: - name: tcp-389 containerPort: 389 protocol: TCP - name: tcp-636 containerPort: 636 protocol: TCP env: - name: LDAP_ORGANISATION value: test - name: LDAP_DOMAIN value: test.com - name: LDAP_ADMIN_PASSWORD value: 123456 - name: LDAP_CONFIG_PASSWORD value: 123456 - name: LDAP_BACKEND value: mdb resources: limits: cpu: 500m memory: 500Mi requests: cpu: 100m memory: 100Mi volumeMounts: - name: volume-8aprj6 mountPath: /etc/ldap/slapd.d - name: volume-hj6df3 mountPath: /var/lib/ldap terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: IfNotPresent restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst serviceAccountName: default serviceAccount: default securityContext: {} imagePullSecrets: - name: local-harbor affinity: {} schedulerName: default-scheduler strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% revisionHistoryLimit: 10 progressDeadlineSeconds: 600 --- ## ldap tool kind: Deployment apiVersion: apps/v1 metadata: name: ldap-phpldapadmin namespace: tool labels: app: ldap-phpldapadmin annotations: kubesphere.io/alias-name: LDAP kubesphere.io/description: LDAP在线工具 spec: replicas: 1 selector: matchLabels: app: ldap-phpldapadmin template: metadata: labels: app: ldap-phpldapadmin spec: containers: - name: container-jojizv image: 'osixia/phpldapadmin:stable' ports: - name: tcp-443 containerPort: 443 protocol: TCP - name: tcp-80 containerPort: 80 protocol: TCP env: - name: PHPLDAPADMIN_HTTPS value: 'false' - name: PHPLDAPADMIN_LDAP_HOSTS value: 10.100.100.11 //这里要和ldap-server的cluster ip一致,网段根据实际修改 resources: limits: cpu: 500m memory: 500Mi requests: cpu: 10m memory: 10Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: IfNotPresent securityContext: privileged: true restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst serviceAccountName: default serviceAccount: default securityContext: {} imagePullSecrets: - name: local-harbor affinity: {} schedulerName: default-scheduler strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% revisionHistoryLimit: 10 progressDeadlineSeconds: 600 --- ## svc kind: Service apiVersion: v1 metadata: name: ldap-server-svc namespace: tool labels: app: ldap-server-svc spec: ports: - name: tcp-389 protocol: TCP port: 389 targetPort: 389 nodePort: 30944 - name: tcp-636 protocol: TCP port: 636 targetPort: 636 nodePort: 31282 selector: app: ldap-server clusterIP: 10.100.100.11 type: NodePort sessionAffinity: ClientIP externalTrafficPolicy: Cluster --- ## svc kind: Service apiVersion: v1 metadata: name: ldap-phpldapadmin-svc namespace: tool labels: app: ldap-phpldapadmin-svc spec: ports: - name: tcp-80 protocol: TCP port: 80 targetPort: 80 nodePort: 30581 selector: app: ldap-phpldapadmin clusterIP: 10.100.100.12 type: NodePort sessionAffinity: ClientIP externalTrafficPolicy: Cluster --- ## pvc kind: PersistentVolumeClaim apiVersion: v1 metadata: name: ldap-data-pvc namespace: tool labels: app: ldap-data-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi storageClassName: ldap volumeMode: Filesystem --- ## pvc kind: PersistentVolumeClaim apiVersion: v1 metadata: name: ldap-config-pvc namespace: tool labels: app: ldap-config-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi storageClassName: ldap volumeMode: Filesystem
部署后使用http://nodeip:30581访问PHP的ldap管理页面,登录信息见LDAP_DOMAIN等env,上述例子登录名就是cn=admin,dc=test,dc=com,密码是123456

4.openLDAP的后续问题

4.1 匿名登录

网友的说法:默认允许匿名登录,LDAP Admin客户端测试登录可以看到组织信息,如下图
notion image
但是我在默认的配置下,匿名登录看不到组织信息
  • LDAP Admin客户端匿名测试连通性OK
notion image
  • LDAP Admin客户端匿名登录报错:
notion image
  • phpldapadmin可以匿名登录,但看不到组织详细的信息
notion image
所以没有管匿名登录的事了

4.2 ldap普通用户的权限

  • 最开始以为普通用户登录可以看到全部信息,实际并不是,登录上去和匿名用户界面一样。
notion image
  • ldap登录名必须是完整的串,比如cn=li lei,cn=ops,ou=acompany,dc=chawn,dc=com其他人即使知道自己的cn,也通常不知道详细组织,故登录成功的可能性很小。

4.3 备份和恢复

按传统的做法,可以选择命令备份,也可以通过phpldapadmin控制台export导出备份。现在既然是deployment挂载volume,那只需要对这个volume备份即可。
或者参考docker备份方案:osixia/openldap-backup

4.4 管理员密码重置

如果管理员密码忘记,可以不需要原密码做重置操作,前提是有进入ldap-server容器的权限。下面是重置示范,参考

4.4.1 进入ldap-server容器

kubectl -n tool exec ldap-server-68997f7b5b-q6frw -it -- /bin/sh

4.4.2 拿到数据库的dn

ldapsearch -H ldapi:// -LLL -Q -Y EXTERNAL -b "cn=config" "(olcRootDN=*)" dn olcRootDN olcRootPW
💡
注意是olcDatabase={1}mdb,cn=config
# ldapsearch -H ldapi:// -LLL -Q -Y EXTERNAL -b "cn=config" "(olcRootDN=*)" dn olcRootDN olcRootPW dn: olcDatabase={0}config,cn=config olcRootDN: cn=admin,cn=config olcRootPW: {SSHA}b6h6fT8fOK3EXHibFVRfvfs4L6Yc/3 dn: olcDatabase={1}mdb,cn=config olcRootDN: cn=admin,dc=chawn,dc=com olcRootPW: {SSHA}+kbvSl6mNxFaaBx2dHaus+gyYLpMqG

4.4.3 配置新的密码

slappasswd -s newpasswd
# slappasswd -s 123456 {SSHA}Z3K8w3EVC0mG9/t3uLJyWjIK/HsBgk //此行是配置后的输出

4.4.4 编写重置文件

cat > newpasswd.ldif <<EOF dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcRootPW olcRootPW: {SSHA}Z3K8w3EVC0mG9/t3uLJyWjIK/HsBgk EOF

4.4.5 重置文件导入

ldapmodify -H ldapi:// -Y EXTERNAL -f newpasswd.ldif
# ldapmodify -H ldapi:// -Y EXTERNAL -f newpasswd.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={1}mdb,cn=config" //说明重置写入成功

5.Jenkins集成示范

notion image
  • 安全域:“LDAP”,Server输入LDAP服务器地址,有其他配置可以点击“Advanced Server Configuration…”
💡
安全域的各项是互斥关系,默认是Jenkins专有数据库,一旦选择ldap,Jenkins原有的用户就失去权限。故在使用ldap前确保已新增ldap用户,Jenkins的rbac授予了该用户admin权限。
  • Server:服务器地址,可以直接填写LDAP服务器的主机名或IP,例如ldap.domain.com(默认端口389),或者ldap.domain.com:1389,如果用了SSL,可以填写ldaps://ldap.domain.com(默认端口636),或者ldaps://ldap.domain.com:1636
  • root DN:这里的root DN只是指搜索的根,并非LDAP服务器的root dn。由于LDAP数据库的数据组织结构类似一颗大树,而搜索是递归执行的,理论上,我们如果从子节点(而不是根节点)开始搜索,因为缩小了搜索范围那么就可以获得更高的性能。这里的root DN指的就是这个子节点的DN,当然也可以不填,表示从LDAP的根节点开始搜索
  • User search base:这个配置也是为了缩小LDAP搜索的范围,例如Jenkins系统只允许ou为Admin下的用户才能登陆,那么你这里可以填写ou=Admin,这是一个相对的值,相对于上边的root DN,例如你上边的root DN填写的是dc=domain,dc=com,那么user search base这里填写了ou=Admin,那么登陆用户去LDAP搜索时就只会搜索ou=Admin,dc=domain,dc=com下的用户了
  • User search filter:这个配置定义登陆的“用户名”对应LDAP中的哪个字段,如果你想用LDAP中的uid作为用户名来登录,那么这里可以配置为uid={0}({0}会自动的替换为用户提交的用户名),如果你想用LDAP中的mail作为用户名来登录,那么这里就需要改为mail={0}。在测试的时候如果提示你user xxx does not exist,而你确定密码输入正确时,就要考虑下输入的用户名是不是这里定义的这个值了
  • Group Search base:参考上边User search base解释
  • Group search filter:这个配置允许你将过滤器限制为所需的objectClass来提高搜索性能,也就是说可以只搜索用户属性中包含某个objectClass的用户,这就要求你对你的LDAP足够了解,一般我们也不配置
  • Group membership:没配置,没有详细研究
  • Manager DN:这个配置在你的LDAP服务器不允许匿名访问的情况下用来做认证(详细的认证过程参考SVN集成OpenLDAP认证中关于LDAP服务器认证过程的讲解),通常DN为cn=admin,dc=domain,dc=com这样
  • Manager Password:上边配置dn的密码
  • Display Name LDAP attribute:配置用户的显示名称,一般为显示名称就配置为uid,如果你想显示其他字段属性也可以这里配置,例如mail
  • Email Address LDAP attribute:配置用户Email对应的字段属性,一般没有修改过的话都是mail,除非你用其他的字段属性来标识用户邮箱,这里可以配置
下边还有一些配置如:环境变量Environment Properties、servlet容器代理等,很少用就不多解释了。有一个配置Enable cache可能会用得到,当你的LDAP数据量很大或者LDAP服务器性能较差时,可以开启缓存,配置缓存条数和过期时间,那么在过期时间内新请求优先查找本地缓存认证,认证通过则版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!不会去LDAP服务器请求,以减轻LDAP服务器的压力

6. 参考

技术
  • devops
  • k8s故障排查Jenkins scripted pipeline使用sshagent和参数
    目录