{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/jenkins-svn-credential-management/",
  "atlas": "https://www.pystone.net/?node=jenkins-svn-credential-management#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/jenkins-svn-credential-management.md",
  "context": "https://www.pystone.net/notes/jenkins-svn-credential-management.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:jenkins-svn-credential-management",
  "slug": "jenkins-svn-credential-management",
  "title": "Jenkins 执行 SVN 更新时的凭据管理",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "Jenkins 执行 SVN 更新时的凭据管理",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "0d0a28b3caeff483dc234599e2b97268db0be11d6436de7ff172dedd3bc8a84e",
  "assets": [],
  "headings": [
    {
      "depth": 1,
      "text": "Jenkins 执行 SVN 更新时的凭据管理",
      "anchor": "jenkins-执行-svn-更新时的凭据管理",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#jenkins-%E6%89%A7%E8%A1%8C-svn-%E6%9B%B4%E6%96%B0%E6%97%B6%E7%9A%84%E5%87%AD%E6%8D%AE%E7%AE%A1%E7%90%86"
    },
    {
      "depth": 2,
      "text": "不要把密码写进命令",
      "anchor": "不要把密码写进命令",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#%E4%B8%8D%E8%A6%81%E6%8A%8A%E5%AF%86%E7%A0%81%E5%86%99%E8%BF%9B%E5%91%BD%E4%BB%A4"
    },
    {
      "depth": 2,
      "text": "SVN 客户端的认证缓存",
      "anchor": "svn-客户端的认证缓存",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#svn-%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E8%AE%A4%E8%AF%81%E7%BC%93%E5%AD%98"
    },
    {
      "depth": 2,
      "text": "Jenkins 的推荐方式",
      "anchor": "jenkins-的推荐方式",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#jenkins-%E7%9A%84%E6%8E%A8%E8%8D%90%E6%96%B9%E5%BC%8F"
    },
    {
      "depth": 2,
      "text": "macOS Agent",
      "anchor": "macos-agent",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#macos-agent"
    },
    {
      "depth": 2,
      "text": "参考资料",
      "anchor": "参考资料",
      "citation": "https://www.pystone.net/notes/jenkins-svn-credential-management/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:software-engineering-and-quality",
      "title": "软件工程与质量保障",
      "url": "https://www.pystone.net/notes/software-engineering-and-quality/",
      "atlas": "https://www.pystone.net/?node=software-engineering-and-quality#knowledge-atlas",
      "label": "软件工程与质量保障",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "CI-CD与质量保障/CI-CD工具链中的“【Jenkins】svn up密码存储问题”导航项",
      "citation": "https://www.pystone.net/notes/software-engineering-and-quality/#ci-cd%E4%B8%8E%E8%B4%A8%E9%87%8F%E4%BF%9D%E9%9A%9Cci-cd%E5%B7%A5%E5%85%B7%E9%93%BE"
    }
  ],
  "contentMarkdown": "# Jenkins 执行 SVN 更新时的凭据管理\n\n> [!note] 内容已脱敏\n> 早期排障记录中的账号、口令、内部路径和截图已移入私有工作资料；本文只保留可公开复用的方法。\n\n## 不要把密码写进命令\n\n以下做法都会扩大泄露面：\n\n- 在流水线、Shell 历史或笔记中写明文密码；\n- 把密码放入命令行参数，使其可能出现在进程列表或日志中；\n- 为了“省事”而强制 SVN 以明文形式缓存凭据；\n- 让多个任务共用个人账号或同一个高权限工作目录。\n\n## SVN 客户端的认证缓存\n\n命令行 SVN 通常把认证元数据保存在当前执行用户的 `~/.subversion/auth/` 下，并可能借助操作系统密钥环保存秘密。Jenkins 以哪个系统用户运行，便读取哪个用户的配置与密钥环；交互式终端可用而流水线不可用，常见原因正是执行用户、HOME、会话或密钥环不同。\n\n排查时依次确认：\n\n1. Jenkins Agent 的实际系统用户与 HOME。\n2. 该用户是否有仓库与工作副本权限。\n3. 系统密钥环在非交互会话中是否可解锁。\n4. SVN 客户端的 `password-stores` 与缓存策略是否符合组织安全要求。\n\n不要通过修改 SVN 源码、降低密钥环安全性或复制个人缓存来规避认证问题。\n\n## Jenkins 的推荐方式\n\n将仓库账号保存到 Jenkins Credentials，并以凭据 ID 绑定到需要的步骤。优先使用 SCM 插件本身的凭据配置；必须运行命令行 SVN 时，再通过受控环境变量或临时认证配置传递。\n\n```groovy\nwithCredentials([usernamePassword(\n  credentialsId: 'svn-service-account',\n  usernameVariable: 'SVN_USER',\n  passwordVariable: 'SVN_PASSWORD'\n)]) {\n  sh 'set +x; ./scripts/update-working-copy.sh'\n}\n```\n\n脚本应从环境读取秘密，禁用命令回显，并确保临时文件不会进入工作区归档。掩码只能降低误输出概率，不能阻止恶意或不受信任步骤主动读取秘密，因此高信任与低信任任务应使用不同 Agent。\n\n## macOS Agent\n\nmacOS 的钥匙串依赖登录会话。后台服务或 SSH 会话可能无法访问交互式登录钥匙串。更稳妥的选择是：\n\n- 使用专用构建账号与专用钥匙串；\n- 在 Agent 启动流程中受控地解锁所需钥匙串，并限制文件权限；\n- 能使用 SSH 密钥或短期令牌时，不复用个人密码；\n- 将签名钥匙串与源码仓库凭据分开管理。\n\n## 参考资料\n\n- [Jenkins Credentials Binding 插件](https://plugins.jenkins.io/credentials-binding)\n- [Subversion Book：凭据缓存](https://svnbook.red-bean.com/en/1.8/svn.serverconfig.netmodel.html#svn.serverconfig.netmodel.credcache)\n"
}
