ldap
ldap
什么是ldap
首先LDAP是一种通讯协议,LDAP支持TCP/IP。协议就是标准,并且是抽象的。在这套标准下,AD(Active Directory)是微软出的一套实现。
那AD是什么呢?暂且把它理解成是个数据库。也有很多人直接把LDAP说成数据库(可以把LDAP理解成存储数据的数据库)。像是其他数据库一样,LDAP也是有client端和server端。server端是用来存放资源,client端用来操作增删改查等操作。
而我们通常说的LDAP是指运行这个数据库的服务器。
可以简单理解AD =LDAP服务器+LDAP应用。
用途
用于统一认证管理,统一公司内部服务账号密码。
LDAP 模型
基本模型
目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。
对象类:是某个实体类型对应的一组属性,对象类可以继承,父类的必须属性也会被继承下来。
属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。
关键字 | 英文全称 | 含义 |
---|---|---|
dc | Domain Component | 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置) |
uid | User Id | 用户ID songtao.xu(一条记录的ID) |
ou | Organization Unit | 组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织) |
cn | Common Name | 公共名称,如“Thomas Johansson”(一条记录的名称) |
sn | Surname | 姓,如“许” |
dn | Distinguished Name | “uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一) |
rdn | Relative dn | 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson” |
dn :一条记录的详细位置。目录位置
dc :一条记录所属区域 (哪一颗树)。根名称
ou :一条记录所属组织 (哪一个分支)。组名称
cn/uid:一条记录的名字/ID (哪一个苹果名字)。用户名称
![img](https://koko-club.github.io/post-images/ldap/ldap_tree.png)
信息模型
LDAP中,信息以树状方式进行组织的,在树状信息中的基本数据单元是条目,而每个条目由属性构成,属性中存储有属性值;
命名模型
即LDAP中的条目定位方式,在LDAP中每个条目均有自己的DN。
DN是该条目在整个树中的唯一名称标识,
如同文件系统中,带路径的文件名就是DN。
功能模型
在LDAP中共有四类10种操作︰
查询类操作:如搜索、比较;
更新类操作:如添加条目、删除条目、修改条目、修改条目名;
认证类操作:如绑定、解绑定;
其它操作:如放弃和扩展操作。
除了扩展操作,另外9种是LDAP的标准操作﹔
扩展操作是LDAP中为了增加新的功能,提供的一种标准的扩展框架,当前已经成为LDAP标准的扩展操作,有修改密码和startTLS扩展,
在新的RFC标准和草案中正在增加一些新的扩展操作,不同的LDAP厂商也均定义了自己的扩展操作。
安全模型
安全模型主要通过身份认证、安全通道和访问控制来实现。
ldap server
一般ldap服务端比较常用的是openldap,这里仅记录openldap的部署及使用。
openldap
k8s部署
直接用yaml部署就行,镜像用的是bitnami的ldap镜像
apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap
spec:
replicas: 1
selector:
matchLabels:
app: openldap
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: openldap
spec:
containers:
- env:
- name: LDAP_ADMIN_USERNAME
value: admin
- name: LDAP_ADMIN_PASSWORD
value: "123456"
- name: LDAP_USERS
value: manager
- name: LDAP_PASSWORDS
value: "123456"
- name: LDAP_ROOT
value: dc=finsiot,dc=com
image: bitnami/openldap:latest
imagePullPolicy: Always
name: openldap
ports:
- containerPort: 1389
name: service
protocol: TCP
resources:
limits:
cpu: "1"
memory: 2Gi
requests:
cpu: "1"
memory: 2Gi
volumeMounts:
- mountPath: /bitnami/openldap/data
name: openldap-pvc
subPath: ldap
- mountPath: /bitnami/openldap/slapd.d
name: openldap-pvc
subPath: slapd.d
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: openldap-pvc
persistentVolumeClaim:
claimName: ldap-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ldap-pvc
labels:
app: ldap
spec:
storageClassName: csi-rbd-sc #这里的storageclass是我们之前申请的
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: Service
metadata:
name: openldap
spec:
#clusterIP: 192.168.110.29
#externalTrafficPolicy: Cluster
ports:
- nodePort: 30300
port: 1389
protocol: TCP
targetPort: service
selector:
app: openldap
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
ldap二进制部署
这里没有尝试过二进制部署ldap,后面会写。
ldap管理
管理操作ldap数据可以使用ldap客户端或者ldap管理服务工具实现。如果使用ldap windows客户端可以下载LDAPSoft Ldap Browser使用,如果使用管理web页面可以部署服务:ldapphpadmin。
ldapphpadmin
k8s部署
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.16.0 (0c01309)
creationTimestamp: null
labels:
io.kompose.service: phpldapadmin
name: phpldapadmin
spec:
replicas: 1
strategy: {}
selector: #定义选择器
matchLabels: #匹配上面的标签
io.kompose.service: phpldapadmin #匹配模板名称
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: phpldapadmin
spec:
containers:
- env:
- name: PHPLDAPADMIN_HTTPS
value: "false"
- name: PHPLDAPADMIN_LDAP_HOSTS
value: 'ldap://192.168.110.29:30389'
image: osixia/phpldapadmin:0.7.1
name: phpldapadmin
ports:
- containerPort: 80
resources: {}
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:ZZ
labels:
io.kompose.service: phpldapadmin
name: phpldapadmin
spec:
ports:
- name: "8080"
port: 8080
targetPort: 80
selector:
io.kompose.service: phpldapadmin
ldap for nexus
本文主要为nexus集成到ldap的配置,由于网上关于该功能的配置大都层次不齐且写的太模糊,故记录此文档。
1、ldap配置
这里ldap用的是openldap,所以首先需要部署好openldap。首先想要在nexus中集成ldap,ldap的服务端必须要有组和用户。
这里的组用来映射与nexus的角色,使其组下面的用户都拥有nexus映射角色的权限,无需额外配置。
这里的用户则用来登录nexus。
所以需要创建好组和用户,这里以映射一个nexus管理员为例子,首先创建准备好ldap的用户和组:
创建一个ou为nexus,组为manager,用户为nexus,先创建组,然后创建用户指定组。
组:cn=manager,ou=nexus,dc=finsiot,dc=com
用户:cn=nexus,ou=nexus,dc=finsiot,dc=com
![image-20221110171353237](https://koko-club.github.io/post-images/ldap/image-20221110171353237.png)
2、nexus配置
1.访问nexus-web管理页面,登录管理员账号,进入设置-》secruity-》LDAP-》create connection
2.connection配置:
name:这个是要创建的ldap名称,可以随便填,非关键性参数。
Ldap server address:填入ldap地址
Search base Dn:填入dn地址(dc的地址)
Authentication method: Simple Authentication
Username or DN: 填入登录用户名(一般用admin管理员登录)
password: 密码
3.User and group配置:
configuration template: 选择一个模板,非关键性参数,只是会预先给出下面一些参数的值。这里可以选posix with static groups
user relative dn(base dn):对应于用作用户条目基础的专有名称集合。此DN与前面的search base相关。例如,如果用户都包含在ou = nexus,dc=finsiot,dc=com中,前面登录时指定了dc=finsiot,dc=com的搜索库,则这里使用值ou = nexus。
User subtree: 如果基本DN下面的树可以包含用户条目,则值为true;如果所有用户都包含在指定的基本DN中,则为false。例如,如果所有用户都在ou = users,dc = sonatype,dc = com,则此字段应为False。如果用户可以在组织单位内的组织单位中显示,例如ou = development,ou = users,dc = sonatype,dc = com,则此字段应为True。
Object class: 此值是RFC-2798中定义的标准对象类。它为用户指定对象类。常见值为inetOrgPerson,person,user或posixAccount。这里使用模板默认的posixAccount
User filter: 这允许您配置过滤器以限制对用户记录的搜索。它可以用作性能改进。这里不用填写。
User ID attribute: 这是上面指定的对象类的属性,它从LDAP服务器提供用户的标识符。存储库管理器使用此属性作为用户ID值。在ldap创建了用户以后,里面有一个属性值(默认为uid),例如我这里创建了一个nexus的用户,则会有一个uid的值为nexus,nexus服务需要通过这个key:value来找到该用户
Real name attribute: 这是Object类的属性,它提供用户的真实姓名。存储库管理器在需要显示用户的真实姓名时使用此属性,类似于内部名字和姓氏属性的使用。这个也是去找ldap里面的kv属性,默认是key的名称为cn。
Email attribute: 同上面的User ID attribute和Real name attribute,默认key的名称为mail。
Password attribute:不用填写,这里为空则会在登录时读取ldap中用户的password字段。
Map LDAP groups as roles:这里需要勾选,下面是组的配置,用于将ldap组映射于nexus。
Group type: static Groups 这里选择静态组
Group relative DN: 指名组的DN位置,例如我这里manager组在nexus下面,则这里填ou=nexus。
Group subtree: 勾选,表示是位于group下面的子组。例如我上面ou=nexus,则这里勾选的意思是nexus下面的组。
Group object class: 组创建时会有这个字段,默认为posixGroup。和上面定义User ID attribute和Real name attribute和Email attribute是一样的。
Group ID attribute: 这里表示组的id属性,和上面定义User ID attribute和Real name attribute和Email attribute是一样的。
Group member attribute: 这里表示组里面有哪些成员,和上面两个属性一样,也是ldap组中的字段,但默认不会创建这个字段,请手动创建memberUid的字段并把成员的字段值写入该字段,否则会找不到映射的角色。
Group member format: 该字段用来找到memberUid中的组员名称的,使用变量${username}。
![image-20221110171338946](https://koko-club.github.io/post-images/ldap/image-20221110171338946.png)
![image-20221110171215302](https://koko-club.github.io/post-images/ldap/image-20221110171215302.png)
![image-20221110171237900](https://koko-club.github.io/post-images/ldap/image-20221110171237900.png)
![image-20221110171249864](https://koko-club.github.io/post-images/ldap/image-20221110171249864.png)
创建角色
在nexus设置-》security-》roles中添加一个role,type为external role mapping,external role type为ldap。
![image-20221110171612944](https://koko-club.github.io/post-images/ldap/image-20221110171612944.png)
Mapped Role:请填写为ldap中创建的组名称,两个服务会通过名称进行映射,例如我这里ldap中有一个nexus用户,在manager组下面,于是这里我定义一个mapped role为manager,则nexus以及ldap中manager组中所有用户都会拥有这里定义好的权限,也就是组权限映射。
Role Name: role角色的名称。
Role Description: 角色介绍。
Privileges:定义的是角色的权限。
Roles:可以与其它定义好的role关联权限。
测试
创建好以后回到刚刚的ldap设置,点击刚刚创建的ldap,进入user and group设置,最下方有一个 verify user mapping 。
![image-20221110171936912](https://koko-club.github.io/post-images/ldap/image-20221110171936912.png)
点击属于ldap密码就可以看到目前定义映射的组和用户情况
![image-20221110172056058](https://koko-club.github.io/post-images/ldap/image-20221110172056058.png)
这里user id其实就是上面user id attribute配置,name为Real name attribute配置,email为Email attribute,roles是Map LDAP groups as roles及下面所有组配置定义的。如果有没有数据的字段,请检查该项对应配置的字段是否正常配置,例如如果roles没有,请看一下Map LDAP groups as roles下面的配置是否正确。
ldap for jenkins
jenkins集成ldap的方法
1、安装插件
![Jenkins安装LDAP插件](https://koko-club.github.io/post-images/ldap/cb436a8c487d4df0b47bfea2f494bf77.png)
2、配置ldap
进入管理设置(manage jenkins)->全局安全设置(configure global security),设置安全域为ldap
![image-20230210101753775](https://koko-club.github.io/post-images/ldap/image-20230210101753775.png)
配置项
Server:ldap的地址url
root DN:根DN目录路径
User search base:查找用户的目录
User search filter:查找用户的条件
Group search base: 查找用户组的目录
Group search filter: 用户组条件(查找用户的条件)
Group membership:选择 Search for LDAP groups containing user
Manager DN: 管理员所在路径
Manager Password: 管理员密码
Display Name LDAP attribute: jenkins对应ldap用户名的字段
Email Address LDAP attribute:email字段
配置示例:
![image-20230210102814010](https://koko-club.github.io/post-images/ldap/image-20230210102814010.png)
这里ldap的结构为,用户目录:ou=people,dc=xxx,dc=com,用户组目录:ou=group,dc=xxx,dc=com
![image-20230210103422255](https://koko-club.github.io/post-images/ldap/image-20230210103422255.png)
![image-20230210103437606](https://koko-club.github.io/post-images/ldap/image-20230210103437606.png)
这里需要注意的点是:user search filter用于找到用户,如果这里填错了将会找不到用户。group search base则是用于找到用户组,如果这里填错了将找不到用户,而search filter用于找到用户组中的用户(&(objectClass=posixGroup)(memberUid={1})),这里的用户组主要用于授权时使用,对组进行授权。
测试
配置完成可以点击test ldap settings测试一下:
![image-20230210104457142](https://koko-club.github.io/post-images/ldap/image-20230210104457142.png)
![image-20230210104515248](https://koko-club.github.io/post-images/ldap/image-20230210104515248.png)
ldap for gitlab
gitlab并不能直接通知页面设置来对接ldap,而是通过配置文件。
1、ldap配置(二进制部署)
这里配置分为两种:一种是二进制包部署的gitlab,这个由于我并没有部署过,所以下面的配置摘抄于网上,不清楚版本有没有配置变化,但配置大致的字段基本应该是一致的;还有一种方法是k8s的配置,这种也是目前我在使用的方式,会在下面列出来。
如果是二进制部署的则直接更改配置文件
vi /etc/gitlab/gitlab.rb
gitlab_rails['ldap_enabled'] = true
gitlab_rails['prevent_ldap_sign_in'] = false
gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'LDAP', # 随便自定义
'host' => '10.0.20.19', # ldap的server地址
'port' => 389, # ldap端口
'uid' => 'cn', # 配置为cn或者sn都可以,但要注意用户名称将会以此处配置为依据
'bind_dn' => 'cn=admin,dc=aihelp,dc=net', # 管理员账号
'password' => '123456', # 管理员密码
'encryption' => 'plain', # 加密
'allow_username_or_email_login' => false, # 是否启用邮件作为用户名登陆
'block_auto_created_users' => false,
'base' => 'dc=aihelp,dc=net', # 核心配置,表示从哪一层读取用户信息
'user_filter' => '(memberof=cn=jenkins,ou=group,dc=aihelp,dc=net)', # LDAP用户进行过滤
'lowercase_usernames' => false,
'group_base' => '',
'admin_group' => '',
'external_groups' => [],
'sync_ssh_keys' => false
}
}
其中:
label 是显示在GitLab登录框的上方文字描述。
host 和 port 是 LDAP 服务的主机地址及端口
bind_dn 和 password 是一个管理 LDAP 的 dn 及密码
base 表示 LDAP 将以该 dn 为 节点,向下查找用户
user_filter 表示以某种过滤条件筛选用户,比如假设我们只希望所属组为 java-platform 的用户来访问 GitLab,则可以在这里设置 (memberOf=ou=java-platform,ou=people,dc=domain,dc=com)
配置添加之后,依旧像安装时候那样,重载一下配置:
gitlab-ctl reconfigure
Checking LDAP ...
LDAP: ... Server: ldapmain
LDAP authentication... Success
LDAP users with access to your GitLab server (only showing the first 100 results)
DN: uid=test01,ou=people,dc=eryajf,dc=net cn: ceshi
DN: uid=test02,ou=people,dc=eryajf,dc=net cn: test02
DN: uid=test03,ou=people,dc=eryajf,dc=net cn: test03
DN: uid=admin,ou=people,dc=eryajf,dc=net cn: Admin
Checking LDAP ... Finished
使用ldap用户名密码进行登陆即可,此时登陆进去是没有任何项目的权限,如果需要某权限,可以对用户进行组或者单项目的授权。
2、ldap配置(k8s)
ldap这里直接用helm的values.yaml传递配置文件信息,所以在ldap中配置就行了。这里如果是部署也建议采用helm部署,由于gitlab新版本模块过多,如果写yaml文件的话再加上配置文件和需要持久化的存储路径很麻烦,所以使用helm是比较理想的方式。
values.yaml:
----
ldap:
# prevent the use of LDAP for sign-in via web.
preventSignin: false
servers:
main:
label: 'LDAP'
host: '192.168.110.29' #ldap地址
port: 30389 #端口
uid: 'uid'
bind_dn: 'cn=admin,dc=finsiot,dc=com' #管理员路径
password: #管理员密码
secret: my-ldap-password-secret
key: the-key-containing-the-password
encryption: 'plain'
base: 'ou=people,dc=finsiot,dc=com' #用户路径
verify_certificates: true #忽略证书
active_directory: false
allow_username_or_email_login: true #支持邮件和用户名登录
block_auto_created_users: false
user_filter: ''
attributes:
username: ['cn'] #用户名对应ldap字段
email: ['mail','email'] #邮箱对应ldap字段
name: 'description' #用户显示名字对应ldap字段
fister_name: 'givenName'
last_name: 'sn'
需要注意的是,gitlab-ce仅支持ldap的用户配置,不支持ldap用户组的配置,如果想要使用ldap用户组,需要使用gitlab-ee(商业版本)。
ldap的配置文件是configmap:gitlab-webservice下面的gitlab.yml.erb,挂载于gitlab-webservice-default的/var/opt/gitlab/templates/gitlab.yml.erb路径。
gitlab拉取ldap账号数据
问题
ldap与应用结合一般有两种,一种是服务需要登录时去调用ldap的账号数据实现结合,还有一种是服务预先将ldap存在自己数据库中然后通过ldap的账号进行登录。而gitlab则是后者,这种情况会导致新加了账号但是ldap却没办法直接用新账号登录,因为gitlab并非是登录直接去ldap调用,而是从自己数据库中找ldap账号数据。
解决办法
1、定时
可以在gitlab中设置每日定时任务,定时从ldap中拉取数据到自己的数据库。
K8S:
这里k8s是在helm的部署文件values.yaml添加修改:
cron_jobs:
ldap_sync_worker:
cron: "30 1 * * *"
ldap_group_sync_worker:
cron: "0 * * * *"
二进制部署:
请查看官方文档:https://docs.gitlab.cn/jh/administration/auth/ldap/ldap_synchronization.html
2、手动拉取
手动拉取使用gitlab-rake gitlab:ldap:check命令就可以,这个是测试ladp的命令,测试的同时会拉取一遍数据。
如果是k8s需要在gitlab-toolbox容器中执行该命令
mindoc for ldap
mindoc是一款开源wiki服务,由于比较冷门,后面可能几乎用不到,这里就简略记录一下,直接贴上配置文件
app.conf #mindoc配置文件
#是否启用ldap
ldap_enable=true
#ldap主机名
ldap_host=192.168.110.29
#ldap端口
ldap_port=30389
#ldap内哪个属性作为用户名
ldap_attribute=uid
#搜索范围
ldap_base=dc=finsiot,dc=com
#第一次绑定ldap用户dn
ldap_user=cn=admin,dc=finsiot,dc=com
#第一次绑定ldap用户密码
ldap_password=123456
#自动注册用户角色:0 超级管理员 /1 管理员/ 2 普通用户
ldap_user_role=2
#ldap搜索filter规则,AD服务器: objectClass=User, openldap服务器: objectClass=posixAccount ,也可以定义为其他属性,如: title=mindoc
ldap_filter=objectClass=posixAccount
直接配置好重启应用就可以使用ldap账号登录了。
zentao for ldap
禅道服务接入ldap
ldap插件部署
禅道本身不支持ldap,需要额外安装ldap插件。插件地址:https://github.com/yihoyoung/zentao-ldap
需要注意的是目前这个版本最高仅支持禅道12,本人测试在禅道18版本上面不兼容。
其安装步骤在github的readme中有说明:
1.打包 ldap 文件夹为 ldap.zip 文件
2.创建文件:
touch /www/zentaopms/www/ok.txt
3.admin 账户登陆禅道,后台 -> 插件 -> 本地安装,选择打包的 ldap.zip 文件安装即可
具体步骤
下载ldap代码,将这个文件打包成zip。
![image-20230213152207304](https://koko-club.github.io/post-images/ldap/image-20230213152207304.png)
在服务器上面创建该文件:touch /www/zentaopms/www/ok.txt
然后登录禅道管理员账号,部署插件如下:
![image-20230213152502090](https://koko-club.github.io/post-images/ldap/image-20230213152502090.png)
安装文件时提示版本不兼容点击强制安装即可。
![image-20230213152747071](https://koko-club.github.io/post-images/ldap/image-20230213152747071.png)
安装成功以后后台会有ldap配置项:
![image-20230213140948096](https://koko-club.github.io/post-images/ldap/image-20230213140948096.png)
ldap配置说明
LDAP服务器: ldap地址
协议版本: 默认填写3
BindDN: 管理账号地址
BindDN 密码: 管理账户密码
BaseDN: 用户地址
Search filter: 搜索用户的条件,openldap这个服务默认是objectClass=posixAccount,不同的ldap服务不一样
账号字段: 登录用户名字段
EMail 字段: 邮箱字段
姓名字段: 名字字段
ldap配置完以后先点击保存配置,然后点击手动同步,如果有同步的用户信息那就表示没问题了。
![image-20230213153228070](https://koko-club.github.io/post-images/ldap/image-20230213153228070.png)
最后在组织-》用户中查看已经通过ldap导入的用户信息。
注意:配置了ldap以后系统原账号登录需要在用户名前面加上“admin。