大道至简,知易行难
广阔天地,大有作为

Jenkins使用LDAP

Jenkins提供了用户认证和权限控制两种维度的安全策略:
1、Security Realm(安全域):判断用户名和密码是否有效、判断用户所属的group;
2、Authorization Strategy(授权策略):分配用户执行操作的权限;

Jenkins默认的Security Realm是Jenkins’s own user database,而Jenkins使用LDAP并非大部分文章中简单地配置一下LDAP Plugin就能万事大吉的。这些文章大多言之不详,实际上坑比较多。Jenkins使用LDAP主要分为两个关键环节:
1、正确地配置LDAP;
2、合理地配置Jenkins LDAP Plugin;
基本上就是围绕如下的插件配置展开的:

Jenkins配置LDAP登陆及权限控制

Jenkins配置LDAP登陆及权限控制

需要注意, 一旦启用了LDAP,那么本地认证的账户都将无法再使用,所以需要确保LDAP配置正确后再保存,否则一旦有问题就没法登陆了。

一、正确且合理地配置LDAP

主要指相关user、group、membership的search及配置,在LDAP中group主要涉及groupOfNames和groupOfUniqueNames等属性,用memberOf表达people与group的关系。笔者对LDAP完全一无所知,因此直接使用了389 Directory Server自带的example组织架构,事实证明还是脑补出了很多东西,如果不想花时间去了解LDAP的过多细节那么非常推荐从example入手。

memberOf需要在schema中自行定义,否则根本无法添加这个attribute:

LDAP不能在实体中增加memberOf属性

LDAP不能在实体中增加memberOf属性

网上有些关于OpenLDAP手工添加memberOf支持的文章;而对于389 Directory Server而言,有一个默认没有开启的插件MemberOf Plugin:

389 Directory Server的MemberOf插件

389 Directory Server的MemberOf插件

我们将其开启,然后根据文档Run Fix Task来修复开启memberOf插件前就已经存在的实体:

389 Directory Server MemberOf插件的Fixup任务

389 Directory Server MemberOf插件的Fixup任务

然而执行报错,搜索无结果。不过,我们可以手工进行处理,根据文档,在实体上增加一个objectClass=extensibleObject的属性后就能够在people中增加memberOf的属性了:

在LDAP实体中增加memberOf属性

在LDAP实体中增加memberOf属性

对于group而言,有两个objectClass比较重要,即groupOfNames和groupOfUniqueNames,如果group的实体没有这个两个配置的话需要增加上,否则搜索会有问题:

Jenkins中未能正确设置group的search或者group未能正确配置

Jenkins中未能正确设置group的search或者group未能正确配置

我们可以看到Jenkins中对LDAP group的搜索规则:

Jenkins对LDAP中group的默认search

Jenkins对LDAP中group的默认search

因此,在LDAP中作为group使用的ou也需要配置上述两个属性,有这两个属性的ou图标也会发生改变:

LDAP中配置group

LDAP中配置group

这样,把Root DN、之类的配置好,LDAP插件就算是初步配置完成了。接下来多找几个账号、模拟账号不存在、账号存在密码不正确、账号存在密码正确等等的情况进行测试。然而,我们在接下来的“Test LDAP settings”中发现一个诡异的情况,即当输入错误的用户名和密码时,LDAP插件能够读到对应Entity中映射的Attribute;但是当输入正确的用户名和密码时,LDAP插件却不能能够读到对应Entity中映射的Attribute:

在Jenkins中LDAP登陆失败时能够正确读取到实体的属性

在Jenkins中LDAP登陆失败时能够正确读取到实体的属性

在Jenkins中LDAP登陆成功时反而不能读取到实体的属性

在Jenkins中LDAP登陆成功时反而不能读取到实体的属性

该问题搜遍全网没有答案,最后从389 Directory Server的Access Log中看到了端倪:

Jenkins配置LDAP的诡异错误

Jenkins配置LDAP的诡异错误

我们发现Test的逻辑是首先使用Manager DN进行BIND,然后search指定的实体,再BIND到对应的实体上进行search。根据日志的情况看,当输入正确的用户名和密码时,LDAP插件BIND成功后却没有search到自己。为了验证,我们在Apache Directory Studio使用UID=test4,ou=people,dc=example,dc=com的DN登陆到LDAP上,发现test4确实是search不到自己的:

LDAP中以某个people的身份BIND后search不到自己

LDAP中以某个people的身份BIND后search不到自己

这也就解释了为什么Jenkins LDAP插件给出了诡异的报错。接下来,笔者通过参考资料2学习到了需要用aci来控制search的权限:

LDAP Enabling Users to Access Their Own Entries

LDAP Enabling Users to Access Their Own Entries

在people实体上增加如下的一个aci属性:

LDAP Enabling Users to Access Their Own Entries的配置

LDAP Enabling Users to Access Their Own Entries的配置

这样,在Apache Directory Studio使用UID=test4,ou=people,dc=example,dc=com的DN登陆到LDAP上后发现test4能够search到自己了:

LDAP中以某个people的身份BIND后能够search到自己

LDAP中以某个people的身份BIND后能够search到自己

而LDAP插件的测试结果也终于正常了:

Jenkins正确配置LDAP后的测试

Jenkins正确配置LDAP后的测试

点击右上角的用户名称,也能够看到该用户在LDAP中所属的group了:

Jenkins中正确配置LDAP后可以直接看到用户所属的group

Jenkins中正确配置LDAP后可以直接看到用户所属的group

二、授权策略

Jenkins的授权策略有如下几种:

  • Anyone can do anything
  • Legacy mode
  • Logged-in users can do anything,登陆用户可进行所有操作
  • Role-Based Strategy
  • Matrix-based Security
  • Project-based Matrix Authorization Strategy

我们使用的是基于项目的矩阵授权策略:

Jenkins Project-based Matrix Authorization Strategy

Jenkins Project-based Matrix Authorization Strategy

其中的group直接使用LDAP中的group名称即可。我们应该注意到,LDAP中的group被加载到LDAP中后是没有层次关系的,因此需要通过名称合理区分。

Project-based Matrix Authorization Strategy是Matrix-based Security的加强版,Matrix-based针对的是整个系统,而Project-based Matrix Authorization Strategy则可以进一步设置用户在每个具体Project上的权限。由于Project-based Matrix Authorization Strategy是一个全局的配置,因此在Project-based Matrix Authorization Strategy中只能按照最小的权限授权,额外的权限可以到具体的项目权限矩阵中添加。Read是Jenkins中很基础的权限,没有Read权限就登不进Jenkins。

当启用了Project-based Matrix Authorization Strategy后,Project的Configure界面中会出现Enable project-based security的复选框,选中后就可以基于矩阵设置用户能够对该Project操作的权限了:

Jenkins配置具体某个项目的Project-based Matrix Authorization Strategy

Jenkins配置具体某个项目的Project-based Matrix Authorization Strategy

这样就可以实现利用LDAP在Jenkins中细粒度地实现基于组及用户的授权策略了。

参考资料:
1、https://directory.fedoraproject.org/docs/389ds/design/memberof-plugin.html
2、https://access.redhat.com/documentation/en-us/red_hat_directory_server/10/html/administration_guide/defining_bind_rules#enabling_users_to_access_their_own_entries
3、https://www.adimian.com/blog/2014/10/how-to-enable-memberof-using-openldap/

转载时请保留出处,违法转载追究到底:进城务工人员小梅 » Jenkins使用LDAP

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址