☰
Jenkins密码重置实战:停服改config.xml全平台指南
2026/10/2 22:16:40 网站建设 项目流程

1. Jenkins密码忘记重置:这不是“找回”,而是安全机制下的可控接管

Jenkins密码忘记,本质上不是数据丢失问题,而是身份认证系统的一次主动失效——它恰恰证明了Jenkins的安全机制在正常工作。很多人第一反应是“赶紧找回来”,但真实情况是:Jenkins本身不存储明文密码,也不提供传统意义上的“密码找回”功能;它的用户凭证要么存在内置数据库(Jenkins专有用户数据库),要么对接LDAP/Active Directory等外部系统。当你用管理员账号登录失败、又没配置SSO或外部认证时,唯一可靠的路径就是绕过登录界面,直接干预底层认证配置。这个过程不需要重启服务、不依赖网络连通性、不涉及任何第三方工具,核心操作就三步:停服务 → 改配置 → 启服务。我做过不下二十次这类重置,覆盖CentOS 7/8、Ubuntu 20.04/22.04、银河麒麟V10、openEuler 22.03 SP3、Windows Server 2019和macOS Monterey,所有系统底层逻辑一致——Jenkins启动时读取config.xml中的useSecurity开关和authorizationStrategy配置块,而用户数据实际存于$JENKINS_HOME/users/目录下序列化文件中。所谓“重置”,其实是把管理员账户的权限策略临时降级为“允许任何人执行所有操作”,再通过Web界面新建一个带全权限的用户,最后恢复安全策略。整个过程5分钟内完成,且全程可逆、无数据丢失风险。适合运维工程师、DevOps工程师、CI/CD平台维护者,也适合刚接触Jenkins的Java后端开发——只要你能SSH进服务器或打开Windows任务管理器,就能自己搞定。不需要懂Groovy脚本,不需要编译源码,更不需要重装Jenkins。

2. 为什么必须停服务再改config.xml?——深入理解Jenkins的启动加载机制

2.1 Jenkins启动时的认证初始化流程

Jenkins不是边运行边读配置的动态系统,而是一个典型的“启动时快照式加载”应用。它的核心认证链路在jenkins.model.Jenkins类的init()方法中完成,具体分四阶段:

  1. 读取全局配置:JVM启动后,Jenkins首先加载$JENKINS_HOME/config.xml,解析<useSecurity>true</useSecurity>标签,确认是否启用安全控制;
  2. 初始化授权策略:根据<authorizationStrategy class="hudson.security.GlobalMatrixAuthorizationStrategy">等class属性,实例化对应策略类,如GlobalMatrixAuthorizationStrategy或ProjectMatrixAuthorizationStrategy;
  3. 加载用户数据库:若使用Jenkins专有用户数据库(即默认配置),则遍历$JENKINS_HOME/users/目录下所有*.xml文件(每个用户一个文件),反序列化出User对象并注册到内存用户池;
  4. 绑定认证提供者:最后将SecurityRealm(如hudson.security.HudsonPrivateSecurityRealm)与AuthorizationStrategy绑定,形成完整的“谁可以登录”+“登录后能做什么”的闭环。

关键点在于:第3步用户加载只在Jenkins主进程启动瞬间执行一次,后续运行中不会重新扫描users目录。这意味着,如果你在Jenkins运行时直接修改config.xml里的useSecurity为false,Jenkins根本不会感知——它已经完成了安全模块初始化,正在用旧策略处理所有HTTP请求。强行刷新页面只会看到“403 Forbidden”或“Access Denied”,因为认证过滤器早已挂载完毕。

2.2 config.xml中两个决定性字段的作用与修改逻辑

config.xml里真正控制登录入口的,是以下两个字段:

<useSecurity>true</useSecurity> <authorizationStrategy class="hudson.security.GlobalMatrixAuthorizationStrategy"> <permission>hudson.model.Computer.Build:anonymous</permission> <permission>hudson.model.Item.Read:anonymous</permission> <!-- 更多权限行 --> </authorizationStrategy>
  • useSecurity是总开关:设为false时,Jenkins跳过所有认证拦截,所有HTTP请求视为已认证的anonymous用户;
  • authorizationStrategy定义权限矩阵:当useSecurity为true时,该策略决定anonymous用户能做什么;当useSecurity为false时,此字段被完全忽略。

因此,标准重置流程不是“删掉密码”,而是把useSecurity设为false,让Jenkins进入免登录模式,然后通过Web界面创建新管理员用户。这比直接编辑用户XML文件更安全——后者需要手动计算密码哈希值(Jenkins用SHA-256加盐哈希),稍有差错就会导致用户无法登录;而新建用户由Jenkins自身完成哈希计算,零出错率。

提示:不要尝试用文本编辑器直接修改$JENKINS_HOME/users/admin_*/config.xml里的<passwordHash>字段。Jenkins 2.300+版本已弃用MD5哈希,改用PBKDF2WithHmacSHA256算法,盐值随机生成且长度不固定,人工构造几乎不可能成功。实测过三次失败案例,最终都退回config.xml方案。

2.3 为什么不能用Groovy脚本热执行?——Jenkins Script Console的权限陷阱

网上很多教程推荐用Jenkins内置的Script Console(/script路径)执行Groovy代码重置密码,典型代码如下:

import jenkins.model.* import hudson.security.* def instance = Jenkins.getInstance() def user = User.get("admin", false) def password = "newpass123" def realm = instance.getSecurityRealm() realm.createAccount("admin", password) instance.save()

这个方案在Jenkins 2.200之前可行,但现在有三个致命缺陷:

  1. Script Console默认禁用:新安装Jenkins默认关闭Script Console,需先登录才能开启,形成死循环;
  2. 权限校验绕不过:即使你设法启用了Script Console,执行脚本仍需当前登录用户具备hudson.model.Hudson.Administer权限,而密码忘记时你根本登不进去;
  3. SecurityRealm不匹配:上述代码假设使用HudsonPrivateSecurityRealm,但若Jenkins配置了LDAP或GitHub OAuth,realm.createAccount()会抛出UnsupportedOperationException。

我去年在某金融客户现场试过这个方案,结果因客户启用了CAS单点登录,脚本执行直接报错退出,还触发了审计日志告警。最终还是靠停服务改config.xml解决。所以结论很明确:Script Console方案是历史遗留技巧,对现代Jenkins环境已不可靠,应彻底放弃。

3. 全平台实操步骤详解:从Linux到银河麒麟V10、openEuler 22.03 SP3、Windows

3.1 Linux通用流程(含CentOS/Ubuntu/麒麟V10/openEuler)

第一步永远是确认Jenkins进程状态和主目录位置。不同安装方式路径差异很大:

  • RPM/YUM安装(CentOS/RHEL/麒麟V10):
    sudo systemctl status jenkins→ 查看Main PID→sudo systemctl stop jenkins
    Jenkins主目录默认为/var/lib/jenkins,可通过sudo grep -r "JENKINS_HOME" /etc/sysconfig/jenkins确认

  • DEB/APT安装(Ubuntu/Debian):
    sudo systemctl status jenkins→sudo systemctl stop jenkins
    主目录默认/var/lib/jenkins,检查/etc/default/jenkins中JENKINS_HOME变量

  • openEuler 22.03 SP3特别注意:
    openEuler默认使用systemd托管Jenkins,但部分镜像预装了jenkins-2.361.4-1.oe2203.noarch.rpm,其服务文件位于/usr/lib/systemd/system/jenkins.service,需确认ExecStart参数是否指定了--prefix=/jenkins等自定义路径。实测某国产云厂商提供的openEuler镜像中,JENKINS_HOME被硬编码为/opt/jenkins,而非标准路径。

停服务后,编辑config.xml:

sudo nano /var/lib/jenkins/config.xml

找到以下两处并修改:

<!-- 原始配置 --> <useSecurity>true</useSecurity> <authorizationStrategy class="hudson.security.GlobalMatrixAuthorizationStrategy"> <permission>hudson.model.Hudson.Administer:admin</permission> <!-- 其他权限 --> </authorizationStrategy>

改为:

<!-- 修改后配置 --> <useSecurity>false</useSecurity> <!-- 删除整个authorizationStrategy节点,或注释掉 --> <!-- <authorizationStrategy class="hudson.security.GlobalMatrixAuthorizationStrategy"> --> <!-- ... --> <!-- </authorizationStrategy> -->

注意:必须删除或注释authorizationStrategy节点,不能只改useSecurity。因为Jenkins启动时会校验useSecurity=true与authorizationStrategy共存,若useSecurity=false但authorizationStrategy仍存在,会抛出IllegalArgumentException导致启动失败。我在麒麟V10上踩过这个坑,日志显示Failed to initialize Jenkins: java.lang.IllegalArgumentException: Security is disabled but authorization strategy is configured,折腾半小时才发现是注释没写对。

保存后启动Jenkins:

sudo systemctl start jenkins # 等待30秒,检查状态 sudo systemctl status jenkins | grep "active (running)"

此时访问http://your-server-ip:8080,无需登录直接进入Jenkins首页。点击右上角“Admin”→“Manage Jenkins”→“Manage Users”→“Create User”,填入新用户名(如recovery_admin)、密码、邮箱,勾选“Administer Jenkins”权限。创建完成后,立即点击右上角用户名→“Log Out”,再用新账号登录。

3.2 Windows环境操作要点(含Windows Server与桌面版)

Windows下Jenkins通常以Windows服务运行,但也有解压即用的war包模式。判断方式很简单:

  • 打开“服务”管理器(services.msc),查找名为“Jenkins”的服务 → 属于服务模式;
  • 检查C:\Program Files\Jenkins\jenkins.war是否存在 → 属于war包模式;
  • 查看任务管理器中是否有java.exe进程且命令行含-jar jenkins.war→ 属于命令行模式。

服务模式操作:

  1. 以管理员身份打开PowerShell;
  2. 执行Stop-Service Jenkins停止服务;
  3. 找到JENKINS_HOME目录:默认为C:\Program Files\Jenkins,但可通过注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Jenkins下的ImagePath值确认,常见路径还有D:\jenkins或C:\jenkins;
  4. 用记事本或VS Code打开config.xml,修改useSecurity为false并删除authorizationStrategy节点;
  5. 执行Start-Service Jenkins启动服务。

war包模式操作:

  1. 在任务管理器中结束所有java.exe进程(确保无残留Jenkins实例);
  2. 进入Jenkins war包所在目录,如C:\jenkins;
  3. 找到jenkins_home子目录(或通过java -Djenkins.home=C:\jenkins_home -jar jenkins.war命令确认路径);
  4. 编辑C:\jenkins_home\config.xml,同Linux修改逻辑;
  5. 重新执行java -Djenkins.home=C:\jenkins_home -jar jenkins.war启动。

实操心得:Windows下最易出错的是路径权限问题。Jenkins服务默认以Local System账户运行,但config.xml文件可能被当前用户独占锁定。建议用PowerShell以管理员身份执行Get-Process -Id (Get-WmiObject Win32_Service | Where-Object {$_.Name -eq 'Jenkins'}).ProcessId | Stop-Process -Force强制结束进程,再编辑文件。另外,Windows记事本保存UTF-8文件时会自动添加BOM头,可能导致Jenkins解析XML失败,务必用Notepad++或VS Code保存为“UTF-8 无BOM”格式。

3.3 macOS与Docker容器环境特殊处理

macOS上Jenkins多以Homebrew安装或直接运行war包:

  • Homebrew安装:brew services stop jenkins-lts→nano ~/Library/Application\ Support/Jenkins/config.xml→ 修改后brew services start jenkins-lts;
  • War包模式:pkill -f "jenkins.war"→nano $HOME/.jenkins/config.xml→java -jar jenkins.war重启。

Docker环境需进入容器内部操作:

# 查找Jenkins容器ID docker ps | grep jenkins # 进入容器(假设容器名为jenkins-server) docker exec -it jenkins-server /bin/bash # 停止Jenkins进程(Docker内通常无systemd,直接kill) ps aux | grep jenkins | grep -v grep | awk '{print $2}' | xargs kill -9 # 编辑配置 vi /var/jenkins_home/config.xml # 退出容器后重启 docker restart jenkins-server

注意:Docker中JENKINS_HOME默认映射到宿主机卷,如-v /data/jenkins:/var/jenkins_home,因此更推荐在宿主机上直接编辑/data/jenkins/config.xml,避免容器内权限混乱。我在阿里云ACK集群中处理过一个Jenkins Pod密码重置,就是通过kubectl exec -it jenkins-pod -- sh进入后修改,但发现Pod内vi命令缺失,最后用sed -i 's/<useSecurity>true<\/useSecurity>/<useSecurity>false<\/useSecurity>/g' /var/jenkins_home/config.xml一行命令搞定。

4. 重置后的安全加固与权限重建:避免二次失陷

4.1 恢复useSecurity并重建管理员权限矩阵

新账号创建成功后,切勿直接开始构建任务——必须立即恢复安全策略。路径:Manage Jenkins→Configure Global Security:

  • 勾选“Enable security”;
  • “Security Realm”保持默认“Jenkins’ own user database”;
  • “Authorization”选择“Matrix-based security”;
  • 在权限表格中,为新管理员用户(如recovery_admin)勾选全部权限:Overall → Administer、Job → Build、Run → Update等共12项;
  • 为anonymous用户取消所有勾选(防止未登录用户访问);
  • 滚动到底部,点击“Save”。

此时Jenkins会自动重启安全模块,新设置即时生效。你可以登出再用新账号登录验证。

关键细节:Matrix-based security权限表中,“Overall → Read”是基础权限,没有它连Jenkins首页都打不开;“Overall → Administer”是最高权限,赋予用户修改全局配置的能力。我见过有同事只勾选了Job类权限,结果无法进入Manage Jenkins页面,反复刷新报403错误,最后才发现漏了Overall → Read。

4.2 清理残留用户与审计日志核查

Jenkins不会自动删除旧管理员账户,原admin用户仍存在于$JENKINS_HOME/users/目录下。虽然密码未知,但为防万一,建议手动清理:

# Linux/macOS sudo rm -rf /var/lib/jenkins/users/admin_* # Windows PowerShell Remove-Item "C:\Program Files\Jenkins\users\admin_*" -Recurse -Force

同时检查审计日志确认无异常操作:

  • 路径:Manage Jenkins→System Log→All Logs→ 查找hudson.security相关日志;
  • 关键日志条目:User anonymous granted Overall/Administer(免登录模式启用)、User recovery_admin created(新用户创建)、Security configuration updated(安全策略恢复);
  • 若发现Failed login attempt for admin from IP xxx.xxx.xxx.xxx高频记录,说明曾遭暴力破解,需进一步排查防火墙规则。

4.3 预防性措施:建立密码备份与多因素认证

密码忘记本质是运维习惯问题。我给自己维护的Jenkins集群强制执行三条铁律:

  1. 密码明文备份到离线介质:每次修改管理员密码后,用AES-256加密(密码用公司密钥管理服务生成的密钥),存入U盘并锁进保险柜。绝不存云端、绝不发邮件、绝不写在便签上。实测某次硬盘故障,靠U盘里三个月前的加密备份秒级恢复。

  2. 启用API Token替代密码登录:在用户配置页生成长期有效的API Token(如1234abcd5678efgh9012ijkl3456mnop),CI/CD脚本、GitLab webhook、DingTalk通知全部用Token调用Jenkins API,避免密码硬编码。Token可在Manage Jenkins→Configure System→Jenkins Location中设置全局API Token。

  3. 强制启用基于TOTP的双因素认证(2FA):安装tow-factor-auth插件,配置Google Authenticator或Microsoft Authenticator。即使密码泄露,攻击者也无法登录——我负责的12个Jenkins实例中,启用2FA后未发生一起未授权访问事件。

经验教训:去年某项目组因Jenkins密码泄露导致构建脚本被篡改,植入挖矿程序。事后复盘发现,他们用同一个密码管理所有系统(Jenkins、GitLab、Artifactory),且从未启用2FA。现在我们所有Jenkins都强制2FA,密码每90天轮换,API Token按项目隔离,彻底堵死横向移动路径。

5. 常见问题与排查速查表:从启动失败到权限错乱的实战解法

问题现象可能原因排查命令/操作解决方案
Jenkins启动后立即崩溃,日志报java.lang.IllegalArgumentException: Security is disabled but authorization strategy is configuredconfig.xml中useSecurity=false但authorizationStrategy节点未删除或未注释sudo tail -n 50 /var/log/jenkins/jenkins.log用sed -i '/<authorizationStrategy/,/<\/authorizationStrategy>/d' /var/lib/jenkins/config.xml批量删除节点
访问http://ip:8080显示“HTTP ERROR 503 Service Unavailable”Jenkins进程未启动或端口被占用sudo netstat -tuln | grep :8080;sudo systemctl status jenkins杀死占用8080端口的进程:sudo lsof -i :8080 | awk '{print $2}' | xargs kill -9
免登录模式下能进首页,但“Manage Jenkins”菜单消失useSecurity=false生效,但Jenkins认为当前用户是anonymous,而anonymous在Matrix策略中无Overall → Read权限检查config.xml中是否残留<authorizationStrategy>配置彻底删除authorizationStrategy节点,确保config.xml中仅剩<useSecurity>false</useSecurity>
新建用户后无法登录,提示“Invalid username or password”新用户密码含特殊字符(如@#$%)被XML解析器截断查看$JENKINS_HOME/users/newuser_*/config.xml中<passwordHash>字段是否完整创建用户时避免使用<>&'"等XML敏感字符,密码用字母+数字组合
麒麟V10系统中systemctl stop jenkins无效,提示“Unit jenkins.service not found”Jenkins以独立Java进程运行,未注册为systemd服务ps aux | grep jenkins→ 找到PID →kill -9 PID用sudo su -c "nohup java -Djenkins.home=/var/lib/jenkins -jar /usr/share/java/jenkins.war > /dev/null 2>&1 &"后台启动

5.1 启动失败深度诊断:从日志定位根因

Jenkins启动失败90%源于config.xml语法错误。最常犯的错误是:

  • XML标签未闭合:如<useSecurity>false漏写</useSecurity>;
  • 中文标点混入:用中文全角括号()或引号“”代替英文半角;
  • 编码问题:Windows记事本保存的UTF-8带BOM,Linux下解析失败。

诊断步骤:

  1. 手动启动Jenkins查看实时日志:
    cd /var/lib/jenkins sudo java -Djenkins.home=/var/lib/jenkins -jar /usr/share/java/jenkins.war --httpPort=8080
  2. 观察控制台输出,定位报错行号(如Caused by: org.xml.sax.SAXParseException; systemId: file:/var/lib/jenkins/config.xml; lineNumber: 42; columnNumber: 15; ...);
  3. 用xmllint校验XML语法:
    sudo apt install libxml2-utils # Ubuntu/Debian sudo yum install libxml2-devel # CentOS/RHEL xmllint --noout /var/lib/jenkins/config.xml
    若返回空行表示语法正确,否则提示具体错误位置。

5.2 权限错乱终极修复:Groovy脚本强制重置(仅限紧急场景)

当Web界面无法操作时(如UI卡死、JS加载失败),可用Groovy脚本强制重置。此方案仅在config.xml修改无效时启用,且必须在Jenkins运行状态下执行:

  1. 启动Jenkins(即使UI异常,只要HTTP服务起来即可);
  2. 访问http://your-server:8080/script(需已登录,若无法登录则此方案不可用);
  3. 粘贴以下脚本:
import jenkins.model.* import hudson.security.* def instance = Jenkins.getInstance() def realm = new HudsonPrivateSecurityRealm(false) def strategy = new GlobalMatrixAuthorizationStrategy() // 为新用户授予权限 strategy.add(Jenkins.ADMINISTER, "recovery_admin") strategy.add(Item.READ, "recovery_admin") strategy.add(Run.UPDATE, "recovery_admin") // 应用配置 instance.setSecurityRealm(realm) instance.setAuthorizationStrategy(strategy) instance.save() println "Security reset completed. Please log in as 'recovery_admin'."
  1. 点击“Run”执行。

注意:此脚本会覆盖现有所有权限配置,仅保留recovery_admin的管理员权限。执行前务必确认recovery_admin已存在(可通过$JENKINS_HOME/users/目录确认)。我在某次Artifactory与Jenkins集成故障中用过此脚本,当时Jenkins UI完全白屏,但/script接口仍可用,5分钟内恢复全部功能。

6. 附录:各系统JENKINS_HOME路径速查与环境变量验证

Jenkins环境变量直接影响配置路径,必须准确识别。以下为常见系统默认路径及验证命令:

系统类型默认JENKINS_HOME路径验证命令特殊说明
CentOS 7/8/var/lib/jenkinssudo ls -la /var/lib/jenkins/config.xmlRPM包安装路径,/etc/sysconfig/jenkins中JENKINS_HOME可覆盖
Ubuntu 20.04/22.04/var/lib/jenkinssudo cat /etc/default/jenkins | grep JENKINS_HOMEDEB包安装,/etc/default/jenkins中定义
银河麒麟V10/var/lib/jenkins或/opt/jenkinssudo systemctl show jenkins | grep Environment国产化镜像常自定义路径,需查服务Environment变量
openEuler 22.03 SP3/var/lib/jenkinssudo rpm -ql jenkins | grep homeRPM包查询命令,确认文件布局
Windows ServerC:\Program Files\Jenkinsreg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Jenkins" /v ImagePath注册表中ImagePath值指向主目录
macOS (Homebrew)~/Library/Application Support/Jenkinsbrew services list | grep jenkinsHomebrew服务路径,brew --prefix jenkins可查安装根目录
Docker/var/jenkins_homedocker inspect jenkins-server | grep -A 5 "Mounts"宿主机映射路径在Mounts字段中

验证环境变量是否生效的终极命令:

# Linux/macOS sudo -u jenkins bash -c 'echo $JENKINS_HOME' # Windows PowerShell (Get-Service Jenkins).StartType # 查看服务属性中的“登录”选项卡,确认“此账户”路径

最后分享一个小技巧:为避免未来再忘密码,我在每个Jenkins实例的$JENKINS_HOME/init.groovy.d/目录下放一个auto-recovery.groovy脚本,内容如下:

import jenkins.model.* def instance = Jenkins.getInstance() if (!instance.hasPermission(Jenkins.ADMINISTER)) { println "Warning: No admin permission detected. Auto-recovery mode enabled." // 此处可添加告警通知逻辑 }

这个脚本在Jenkins启动时自动执行,若检测到无管理员权限,立即发企业微信告警。上线半年来,已提前发现3次权限异常,全部在业务影响前修复。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询