18.2.4 凭据管理与敏感信息保护

凭据管理与敏感信息保护#

凭据是Jenkins连接外部系统的核心资产,必须做到最小可见、最小使用与全生命周期管理。推荐统一使用Jenkins Credentials System集中管理,禁止在Pipeline脚本、配置文件或日志中明文保存敏感信息。

原理草图:凭据存储与使用路径

flowchart LR
  Dev[开发/运维] -->|创建/更新| CredUI[Jenkins Credentials System]
  CredUI --> Store[凭据存储(域/文件夹/全局)]
  Store --> Job[Job/Folder权限控制]
  Job --> Agent[构建节点/容器]
  Agent --> Ext[外部系统: Git/Registry/DB/Cloud]
  Job -.mask.-> Log[控制台日志(脱敏)]

凭据分类与命名规范
- 按用途分类:源码访问、制品仓库、云平台、数据库、通知通道、签名证书等。
- 采用可追溯命名:业务-环境-系统-用途,如 pay-prod-git-ssh
- 设置明确的描述与负责人,便于审计与交接。

凭据存储与范围控制
- 优先使用Folder级或Job级范围,避免全局暴露。
- dev/test/prod环境分离凭据与权限。
- 结合RBAC限制仅对需要的角色可见与可用。

示例:通过Jenkins CLI导入凭据(可审计、可批量)

前置:下载jenkins-cli.jar,并确保管理员账号已配置API Token

# 1) 下载CLI
wget http://jenkins.example.com/jnlpJars/jenkins-cli.jar

# 2) 准备凭据XML(用户名/密码示例)
cat > /tmp/cred-git.xml <<'EOF'
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
  <scope>GLOBAL</scope>
  <id>pay-prod-git-http</id>
  <description>pay prod git http</description>
  <username>gituser</username>
  <password>gitpass</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
EOF

# 3) 导入到全局域(需管理员权限)
java -jar jenkins-cli.jar -s http://jenkins.example.com \
  -auth admin:APITOKEN \
  create-credentials-by-xml system::system::jenkins _ < /tmp/cred-git.xml

# 预期:返回 "Created credentials"

Pipeline中安全使用凭据
- 使用withCredentialscredentials指令注入变量,避免硬编码。
- 配置日志遮罩,禁止set -x输出敏感变量。

示例:withCredentials安全注入

pipeline {
  agent any
  environment {
    REGISTRY = "registry.example.com"
  }
  stages {
    stage('Login Registry') {
      steps {
        withCredentials([usernamePassword(
          credentialsId: 'pay-prod-registry',
          usernameVariable: 'REG_USER',
          passwordVariable: 'REG_PASS'
        )]) {
          sh '''
            # 禁止调试输出,防止泄露
            set +x
            echo "logging to $REGISTRY"
            echo "$REG_PASS" | docker login $REGISTRY -u "$REG_USER" --password-stdin
          '''
        }
      }
    }
  }
}

敏感信息脱敏与日志保护
- 启用“Secret Masking”,在控制台输出中自动遮罩敏感值。
- 审查脚本中echoset -x等命令。
- 对构建日志设置访问权限与保留策略。

示例:危险命令排查与替换

# 危险:会打印环境变量
set -x
echo "$REG_PASS"

# 安全替换
set +x
echo "registry login ok"

凭据轮换与审计
- 制定轮换策略(30/90天),结合外部系统密钥过期机制。
- 建立变更记录与审计流程,确保可追溯。
- 过期或未使用凭据及时清理。

示例:查询未使用凭据(Groovy脚本控制台)

import com.cloudbees.plugins.credentials.CredentialsProvider
import jenkins.model.Jenkins

def usedIds = [] as Set
Jenkins.instance.items.each { job ->
  def text = job.getConfigFile().asString()
  text.findAll(/credentialsId="([^"]+)"/) { m -> usedIds << m[1] }
}

def all = CredentialsProvider.lookupCredentials(
  com.cloudbees.plugins.credentials.Credentials.class,
  Jenkins.instance, null, null
)

all.each { c ->
  if (!usedIds.contains(c.id)) {
    println "Unused: ${c.id} | ${c.description}"
  }
}

与外部密钥管理系统集成
- 使用Vault、云厂商KMS等作为凭据源,减少本地存储风险。
- 通过插件实现动态凭据与短期Token,提高安全性。

排错清单(常见错误与定位)
1. Pipeline报“Credentials not found”
- 检查凭据ID大小写与作用域(Folder/Global)。
- 确认Job在对应Folder下,且权限允许访问。
2. 日志中仍出现明文密码
- 检查脚本是否set -xecho变量。
- 确认是否使用withCredentials注入。
3. CLI创建凭据失败
- 核对API Token权限。
- 确认XML格式与scopeid字段合法。

练习
1. 创建一个Folder级凭据pay-test-git-ssh,并在该Folder下的Pipeline中完成Git拉取。
2. 将一个Pipeline中的硬编码密码替换为withCredentials注入,并验证日志脱敏效果。
3. 使用Groovy脚本列出未使用凭据,并清理一个无用ID。