---
title: "Jenkins 执行 SVN 更新时的凭据管理"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/jenkins-svn-credential-management/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/03-软件工程与质量保障/CI-CD与质量保障/CI-CD工具链/【Jenkins】svn up密码存储问题.md"
content_hash: 0d0a28b3caeff483dc234599e2b97268db0be11d6436de7ff172dedd3bc8a84e
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# Jenkins 执行 SVN 更新时的凭据管理

> **note · 内容已脱敏**
> 早期排障记录中的账号、口令、内部路径和截图已移入私有工作资料；本文只保留可公开复用的方法。

## 不要把密码写进命令

以下做法都会扩大泄露面：

- 在流水线、Shell 历史或笔记中写明文密码；
- 把密码放入命令行参数，使其可能出现在进程列表或日志中；
- 为了“省事”而强制 SVN 以明文形式缓存凭据；
- 让多个任务共用个人账号或同一个高权限工作目录。

## SVN 客户端的认证缓存

命令行 SVN 通常把认证元数据保存在当前执行用户的 `~/.subversion/auth/` 下，并可能借助操作系统密钥环保存秘密。Jenkins 以哪个系统用户运行，便读取哪个用户的配置与密钥环；交互式终端可用而流水线不可用，常见原因正是执行用户、HOME、会话或密钥环不同。

排查时依次确认：

1. Jenkins Agent 的实际系统用户与 HOME。
2. 该用户是否有仓库与工作副本权限。
3. 系统密钥环在非交互会话中是否可解锁。
4. SVN 客户端的 `password-stores` 与缓存策略是否符合组织安全要求。

不要通过修改 SVN 源码、降低密钥环安全性或复制个人缓存来规避认证问题。

## Jenkins 的推荐方式

将仓库账号保存到 Jenkins Credentials，并以凭据 ID 绑定到需要的步骤。优先使用 SCM 插件本身的凭据配置；必须运行命令行 SVN 时，再通过受控环境变量或临时认证配置传递。

```groovy
withCredentials([usernamePassword(
  credentialsId: 'svn-service-account',
  usernameVariable: 'SVN_USER',
  passwordVariable: 'SVN_PASSWORD'
)]) {
  sh 'set +x; ./scripts/update-working-copy.sh'
}
```

脚本应从环境读取秘密，禁用命令回显，并确保临时文件不会进入工作区归档。掩码只能降低误输出概率，不能阻止恶意或不受信任步骤主动读取秘密，因此高信任与低信任任务应使用不同 Agent。

## macOS Agent

macOS 的钥匙串依赖登录会话。后台服务或 SSH 会话可能无法访问交互式登录钥匙串。更稳妥的选择是：

- 使用专用构建账号与专用钥匙串；
- 在 Agent 启动流程中受控地解锁所需钥匙串，并限制文件权限；
- 能使用 SSH 密钥或短期令牌时，不复用个人密码；
- 将签名钥匙串与源码仓库凭据分开管理。

## 参考资料

- [Jenkins Credentials Binding 插件](https://plugins.jenkins.io/credentials-binding)
- [Subversion Book：凭据缓存](https://svnbook.red-bean.com/en/1.8/svn.serverconfig.netmodel.html#svn.serverconfig.netmodel.credcache)
