Jenkins + SonarQube 从原理到实战三:SonarQube 打通 Windows AD(LDAP)认证与踩坑记录
前言
在前两篇文章中,已经介绍了 SonarQube 的部署 以及 通过 sonar-cxx 插件实现 C/C++ 代码扫描。
本篇将重点讲 如何让 SonarQube 对接 Windows AD(LDAP),实现域账号登录和基于 AD 组的权限管理。
一、背景与需求分析
需求分析
在原有环境中,代码流转流程是这样的:
- 开发在 Gerrit 提交代码
- Jenkins 节点定时或按需触发自定义脚本扫描问题,并执行编译
新需求:
- 在编译之前,先扫描一次代码(或编译+扫描同步进行)
- 项目相关人员 能直接登录 SonarQube 查看代码问题并修复
- 非项目相关人员 无法访问该项目(权限管控)
权限模型简述
SonarQube 的权限是项目级的,可以通过:
- 将项目设为 私有
- 给特定 用户组 或 成员 分配访问所需权限
经测试,权限如下:
角色/权限项 | 组管理(添加/删除成员) | 项目权限配置 | 项目删除 | 备注 |
---|---|---|---|---|
系统管理员(Administrator) | ✅ 可以对任意组添加或删除成员 | ✅ 可以配置任意项目的成员或组权限 | ✅ 可以删除任意项目 | 拥有全局最高权限 |
项目管理员(Project Administrator) | ❌ 无法管理组成员 | ✅ 仅能管理该项目的权限(成员/组) | ✅ 仅能删除该项目 | 该权限需系统管理将项目为私有后才可配置 |
普通组成员 | ❌ 无法管理组成员 | ❌ 无法配置项目权限 | ❌ 无法删除项目 | 系统组没有单独的“组管理员”角色 |
所以这里无法单独给项目设组管理员去维护组成员,但可以配置 项目管理员,由其对相关组或用户进行权限管理 。
碰巧目前我司项目是由 部门/组
进行划分,并且 Windows AD 上早已为这些成员配置了 AD 组
,所以只需要在项目上设 私有
并且给相应的组配置好权限,让 LADP 将要组人员信息同步过来,那就可以减少一部分的人为操作管理。
二、Windows AD 集成
旧版本 SonarQube 需要额外安装 LDAP 插件,而 9.9 LTS 版本(我是用的版本)已经内置了 LDAP 支持。
官方参考文档:
- SonarQube 9.9 LDAP 配置文档
这篇文档,详细介绍了 LDAP 怎么连接、使用、配置参数等,如:
ldap.url
这个参数是指 ldap 的连接地址 - SonarQube 环境变量配置文档
但使用的是k8s
,即容器,该文档介绍了 SonarQube 容器可使用哪些 env 参数。
配置思路
由于我是在 Kubernetes 环境运行 SonarQube,所以我选择:
- 数据库配置与 LDAP 配置都放到 Secret 中,避免明文写在 Deployment YAML
- Deployment 通过
envFrom
读取 Secret
原 Deployment(明文写环境变量)
...
containers:
- name: sonarqubeimage: sonarqube:lts-communityenv:- name: TZvalue: 'Asia/Shanghai'- name: SONAR_JDBC_URLvalue: jdbc:postgresql://postgresql:5432/sonar- name: SONAR_JDBC_USERNAMEvalue: sonar- name: SONAR_JDBC_PASSWORDvalue: sonar- name: SONAR_WEB_JVM_OPTSvalue: "-Xmx2G -Xms1G -XX:+HeapDumpOnOutOfMemoryError"
...
新 Deployment(调用 Secret)
...
containers:
- name: sonarqubeimage: sonarqube:lts-communityenv:- name: TZvalue: 'Asia/Shanghai'- name: SONAR_WEB_JVM_OPTSvalue: "-Xmx2G -Xms1G -XX:+HeapDumpOnOutOfMemoryError"envFrom:- secretRef:name: sonar-secret
...
Secret 配置(secret.yaml
)
apiVersion: v1
kind: Secret
metadata:name: sonar-secretnamespace: sonar
type: Opaque
stringData:SONAR_JDBC_URL: "jdbc:postgresql://postgresql:5432/sonar"SONAR_JDBC_USERNAME: "sonar"SONAR_JDBC_PASSWORD: "sonar"SONAR_SECURITY_REALM: "LDAP" # 启用 LDAP 认证SONAR_AUTHENTICATOR_DOWNCASE: "true" # 登录名转小写,防止大小写问题LDAP_URL: "ldap://192.168.1.1:389" # AD/LDAP 服务器地址(可改成 ldaps:// )LDAP_BINDDN: "CN=sonar,OU=User,OU=AA,DC=aa,DC=com"LDAP_BINDPASSWORD: "sonar" # 绑定账号密码LDAP_AUTHENTICATION: "simple" # 认证方式,一般 simple 就够LDAP_REALM: "aa.com" # 可选,用于某些 Digest 认证LDAP_CONTEXTFACTORYCLASS: "com.sun.jndi.ldap.LdapCtxFactory" # LDAP Java 工厂类LDAP_STARTTLS: "false" # 是否启用 StartTLS(不是 SSL)LDAP_FOLLOWREFERRALS: "false" # 是否跟随 LDAP 引用LDAP_USER_BASEDN: "OU=AA,DC=aa,DC=com" # 用户搜索起始 DNLDAP_USER_REQUEST: "(&(objectClass=user)(sAMAccountName={login}))" # 用户搜索过滤条件LDAP_USER_REALNAMEATTRIBUTE: "cn" # 用户真实姓名属性LDAP_USER_EMAILATTRIBUTE: "mail" # 用户邮箱属性LDAP_GROUP_BASEDN: "OU=Groups,DC=aa,DC=com" # 组搜索起始 DNLDAP_GROUP_REQUEST: "(&(objectClass=group)(member={dn}))" # 组搜索过滤条件LDAP_GROUP_IDATTRIBUTE: "sAMAccountName" # 组 ID 属性
参数解释
变量名 | 作用 |
---|---|
SONAR_SECURITY_REALM | 启用 LDAP 认证 |
SONAR_AUTHENTICATOR_DOWNCASE | 将用户名转换为小写,避免 AD 大小写问题 |
LDAP_URL | LDAP/AD 服务器地址,支持 ldap:// 和 ldaps:// |
LDAP_BINDDN | 用于绑定 LDAP 的账号 DN(需有读取用户/组的权限) |
LDAP_BINDPASSWORD | 绑定账号的密码 |
LDAP_USER_BASEDN | 用户搜索起点 DN |
LDAP_USER_REQUEST | 用户搜索过滤规则 |
LDAP_GROUP_BASEDN | 组搜索起点 DN |
LDAP_GROUP_REQUEST | 组搜索过滤规则 |
LDAP_GROUP_IDATTRIBUTE | 组 ID 属性,一般为 sAMAccountName |
小贴士:
LDAP_BINDDN
格式:
CN=sonar,OU=User,OU=AA,DC=aa,DC=com
表示 aa.com
域下 AA → User 组织单位中的 sonar 用户。
部署与验证
kubectl delete -f sonarqube.yaml
kubectl apply -f secret.yaml && kubectl apply -f sonarqube.yaml
常见启动失败原因:
- 数据库连接信息错误
- LDAP 账号/密码错误
- DN 路径拼写错误
- 网络防火墙拦截 LDAP 端口
若访问有问题,
kubectl logs
看下启动日志,一般就以上问题。
然后使用 AD 域账号浏览器登录 SonarQube ,成功登录即加域成功。
三、AD 组同步的坑
经测试 + 官方声明,发现 SonarQube 是 不会直接把 AD 组以及组内成员同步系统上 。
可以在 SonarQube 上面新建同名 AD 组,重启系统进行同步,当然会存在一些 限制
:
-
组不会自动同步成员
- 只有当成员首次登录 SonarQube 后,系统才会将该成员加入对应组。
- 并且 SonarQube 新建同名组,还得重启服务器生效 。
-
组删除成员不实时
- AD 组删除成员,SonarQube 上面同名组并不会实时删除。
- 需要重启 SonarQube,并且该成员重新登录后,才会被移出组。
-
多层组结构问题
- 如果 AD 中 A 组包含 B 组,B 组里有成员 C,SonarQube 不会识别成员 C 属于 A 组
实际同步流程:
- 新建 SonarQube 组(与 AD 组同名)
- 重启 SonarQube
- AD 组成员登录一次
- 该成员才会被加入组
总结
正式上线前,给 AD 组配置同名组,并给这个同名组配好相关权限。并由 项目管理员 去配置项目权限。
后续 AD 账号登录 SonarQube 就自动加入对应组,即上线就有相应权限。
后续优化:
目前在新建 AD 同名组以及删除 AD 域控上组成员,都必须要重启 SonarQube 服务且 AD 用户重新登录才生效,后续看能不能通过调用 SonarQube 的 API 实现实时权限变更(通过调用 Gerrit/Jenkins 的 API 进行信息匹对)。
当然,也要看正式上线后大家反馈的问题,若有强烈的实时同步需求,就按上面方式进行优化。
下一篇将更新 SonarQube 如何打通 Jenkins。