type
status
date
slug
summary
tags
category
icon
password
1.使用ldap的目的2.ldap的基础概念3.openLDAP的搭建-deployment4.openLDAP的后续问题4.1 匿名登录4.2 ldap普通用户的权限4.3 备份和恢复4.4 管理员密码重置4.4.1 进入ldap-server容器4.4.2 拿到数据库的dn4.4.3 配置新的密码4.4.4 编写重置文件4.4.5 重置文件导入5.Jenkins集成示范 6. 参考
1.使用ldap的目的
Devops流程通常涉及多个web工具,如果每个工具维护一套账号,大一点的项目会非常麻烦。ldap协议非常成熟(古早),故绝大部分平台工具支持此协议。
ldap和各平台集成使用的思路:ldap创建多个ou,在ou下新建用户,平台配置的搜索根指定需要的ou(当然你也可以用
User search base
等配置缩小搜索范围),这样该ou下面的用户就有平台的登录权限。如图所示,你需要让
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的基础概念
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客户端测试登录可以看到组织信息,如下图
但是我在默认的配置下,匿名登录看不到组织信息:
- LDAP Admin客户端匿名测试连通性OK
- LDAP Admin客户端匿名登录报错:
- phpldapadmin可以匿名登录,但看不到组织详细的信息
所以没有管匿名登录的事了
4.2 ldap普通用户的权限
- 最开始以为普通用户登录可以看到全部信息,实际并不是,登录上去和匿名用户界面一样。
- 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集成示范
- 安全域:“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服务器的压力