You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:15:00