如何在Jenkins中为当前构建创建临时密钥存储以适配插件调用需求
解决方法
问题原因说明
- 你第一种直接调用全局系统凭证存储
addCredentials的方案,本身就是会将凭证持久化到Jenkins的磁盘配置文件中,不符合不持久化的要求。 - 你第二种自行实例化
SystemCredentialsProvider的方案无效,因为Jenkins的凭证框架只会扫描已注册为全局扩展点的凭证提供者实例,你自己创建的对象不在框架的识别范围内,所以withCredentials会提示找不到凭证。
方案一:临时注册+构建结束强制删除(兼容所有依赖凭证ID的插件)
直接将凭证临时添加到全局存储,不管构建结果如何,最后强制删除凭证,不会有残留,代码示例如下:
import jenkins.model.Jenkins import com.cloudbees.plugins.credentials.domains.Domain import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey import com.cloudbees.plugins.credentials.CredentialsScope import com.cloudbees.plugins.credentials.SystemCredentialsProvider // 凭证ID添加构建号后缀,避免多构建并发冲突 def tempCredId = "temp-ssh-key-${BUILD_NUMBER}" def credentialStore = null def tempSshKey = null try { def jenkinsInstance = Jenkins.get() def globalDomain = Domain.global() credentialStore = SystemCredentialsProvider.getInstance().getStore() // 这里替换为你从外部存储获取凭证的逻辑 def privateKeyContent = fetchPrivateKeyFromExternalStore() def sshUsername = "your-ssh-username" def sshPassphrase = "your-passphrase" // 无密码短语则填空字符串 def privateKeySource = new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(privateKeyContent) tempSshKey = new BasicSSHUserPrivateKey( CredentialsScope.BUILD, // 构建级作用域,仅当前构建可见 tempCredId, sshUsername, privateKeySource, sshPassphrase, "Temporary SSH key for build ${BUILD_NUMBER}" ) // 临时添加凭证到全局存储 credentialStore.addCredentials(globalDomain, tempSshKey) // 正常执行构建逻辑,通过凭证ID调用临时凭证 withCredentials([ sshUserPrivateKey( credentialsId: tempCredId, keyFileVariable: 'SSH_KEY_PATH', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USER' ) ]) { // 你的业务逻辑,比如SSH远程操作、拉取代码等 sh "ssh -i ${SSH_KEY_PATH} ${SSH_USER}@remote-server 'execute your command'" } } finally { // 构建结束强制删除临时凭证,无论构建成功/失败/异常中断都不会残留 if (credentialStore != null && tempSshKey != null) { credentialStore.removeCredentials(Domain.global(), tempSshKey) // 手动触发保存,确保删除操作持久化,避免Jenkins异常重启后恢复临时凭证 SystemCredentialsProvider.getInstance().save() } }
补充注意事项
如果担心Jenkins中途崩溃导致凭证残留,可以额外配置一个定时清理任务,定期删除描述前缀为Temporary SSH key for build、且对应构建号已结束的凭证即可。
方案二:直接使用临时文件(无需修改Jenkins凭证存储,更安全)
如果你使用的功能不需要传入凭证ID,只是在Pipeline中直接调用SSH等命令,可以直接将从外部获取的凭证写入构建工作区的临时文件,用完删除即可,完全不涉及Jenkins的凭证存储:
// 从外部存储获取私钥内容 def privateKeyContent = fetchPrivateKeyFromExternalStore() // 在当前构建工作区创建临时私钥文件 def tempKeyFile = new File("${WORKSPACE}/temp-ssh-key-${BUILD_NUMBER}.pem") tempKeyFile.text = privateKeyContent // 配置文件权限,避免被其他进程读取 tempKeyFile.setReadable(true, true) tempKeyFile.setWritable(true, true) tempKeyFile.setExecutable(false, false) try { // 直接用临时文件执行命令 sh "ssh -i ${tempKeyFile.absolutePath} ssh-user@remote-server 'your command'" } finally { // 用完删除临时文件 tempKeyFile.delete() }
内容的提问来源于stack exchange,提问作者Tema054
相关产品推荐
相关产品推荐

