Jenkins流水线里的密码还在明文?手把手接入SMS凭据管理系统彻底消灭硬编码
Jenkins流水线密码安全实践指南 摘要:在Jenkins流水线中直接硬编码密码或敏感信息存在严重安全隐患。本文分析了三种常见但危险的凭据管理现状:明文硬编码、Jenkins Credentials插件和环境变量注入,指出其安全缺陷。通过横向对比三种主流方案(Jenkins Credentials、HashiCorp Vault和专用凭据管理系统),推荐采用专业凭据管理系统(SMS)实现最佳安全
Jenkins流水线里的密码还在明文?手把手接入凭据管理系统彻底消灭硬编码
打开GitHub搜索
filename:Jenkinsfile password OR secret OR token,能看到超过百万个包含敏感信息的Jenkins流水线文件。这还只是公开仓库,加上企业内部代码库,这个数字还要翻几倍。本文带你彻底消灭Jenkins流水线里的明文密码。
一、一个真实的开场:GitHub上的"裸奔"密码
2023年,某知名科技公司工程师不小心把包含AWS Secret Key的Jenkinsfile推到了公开仓库,几小时内攻击者就创建了价值数万美元的挖矿实例。
我在GitHub搜索了一下,结果触目惊心:
# 搜索语法
filename:Jenkinsfile "password" language:Groovy
# 结果:超过 120万个公开文件
filename:Jenkinsfile "AWS_SECRET" language:Groovy
# 结果:超过 8万个文件包含AWS密钥
更可怕的是内部仓库——大多数企业的GitLab/GitHub Enterprise里,类似的明文密码散落在数百个Jenkinsfile里,任何有代码仓库读取权限的人都能看到。

二、Jenkins凭据管理的3种现状分析
现状1:直接在Jenkinsfile里写死(最危险)
// Jenkinsfile(错误示范!)
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh "kubectl set image deployment/app app=myapp:${params.VERSION}"
sh "curl -X POST https://deploy.example.com/api/deploy \\
-H 'Authorization: Bearer sk_live_51abcde12345' \\
-d 'version=${params.VERSION}'"
}
}
}
}
问题:任何有代码权限的人都能看到生产部署密钥,离职员工依然能访问历史提交。
现状2:Jenkins Credentials Plugin(有改善,但不够)
Jenkins自带的Credentials插件是最常用的方案:
// Jenkinsfile(使用Credentials插件)
pipeline {
agent any
environment {
// 引用Jenkins里存储的凭据
DOCKER_PASSWORD = credentials('docker-hub-password')
KUBECONFIG = credentials('prod-kubeconfig')
}
stages {
stage('Build') {
steps {
sh 'docker login -u $DOCKER_USER -p $DOCKER_PASSWORD'
sh 'kubectl apply -f deployment.yaml'
}
}
}
}
优点:密码不出现在代码中,Jenkins负责存储。
缺点:
- 凭据分散在各个Jenkins实例里,多实例环境要重复配置
- 没有自动轮换,密码长期不变
- 审计功能弱,无法追溯谁在什么时候用了哪个凭据
- 不支持动态凭据(每次用不同的临时密码)
现状3:环境变量注入(掩耳盗铃)
# 很多团队这样做
export KUBE_API_TOKEN="eyJhbGciOiJSUzI..."
jenkins build -s my-pipeline
问题:环境变量可以被Jenkins日志打印出来,也可以在构建日志里看到,根本不安全。
三、3种主流方案横向对比
| 方案 | 安全性 | 易用性 | 自动轮换 | 审计日志 | 等保合规 |
|---|---|---|---|---|---|
| Jenkins Credentials | ★★☆ | ★★★ | ✗ | ★☆☆ | ✗ |
| HashiCorp Vault Plugin | ★★★★ | ★★☆ | ✓ | ★★★★ | 部分支持 |
| 凭据管理系统(SMS) | ★★★★★ | ★★★★ | ✓ | ★★★★★ | ✓ 完整支持 |
四、手把手接入凭据管理系统(SMS)
以下以安当SMS为例,演示如何在Jenkins流水线中彻底消灭硬编码。
步骤1:安装SMS Jenkins插件
在Jenkins管理界面:
Jenkins → 系统管理 → 插件管理 → 可选插件 → 搜索 "SMS Credentials"
→ 安装 → 重启Jenkins
或者手动安装:
# 下载插件
wget https://plugins.jenkins.io/sms-credentials/sms-credentials.hpi
# 放入Jenkins插件目录
cp sms-credentials.hpi /var/jenkins_home/plugins/
# 重启Jenkins
docker restart jenkins
步骤2:配置SMS服务器连接
Jenkins → 系统管理 → 系统配置 → 找到"SMS Credential Provider"
→ 填写以下信息:
- SMS Server URL: https://sms.internal.company.com
- App ID: jenkins-agent
- App Secret: (点击"添加" → Jenkins → 用Jenkins自己的凭据存储来存这个)
- Namespace: production
- Enable SM4 Encryption: ✓
→ 点击"Test Connection"验证
→ 保存
步骤3:在流水线中使用SMS凭据
// Jenkinsfile(接入SMS后的正确写法)
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout scm
}
}
stage('Docker构建与推送') {
steps {
// 从SMS动态获取Docker Hub密码
withSMSCredential(credentialId: 'docker-hub-prod') {
sh 'docker login -u ${SMS_USERNAME} -p ${SMS_PASSWORD}'
sh 'docker build -t myapp:${BUILD_NUMBER} .'
sh 'docker push myapp:${BUILD_NUMBER}'
}
}
}
stage('K8s部署') {
steps {
withSMSCredential(credentialId: 'k8s-prod-kubeconfig') {
sh 'kubectl set image deployment/app app=myapp:${BUILD_NUMBER}'
sh 'kubectl rollout status deployment/app'
}
}
}
stage('通知部署完成') {
steps {
withSMSCredential(credentialId: 'feishu-webhook') {
sh '''curl -X POST "${SMS_WEBHOOK_URL}" \
-H "Content-Type: application/json" \
-d "{\\"text\\":\\"部署完成,版本:${BUILD_NUMBER}\\"}"'''
}
}
}
}
post {
always {
// 清理:SMS凭据不会留在构建日志里
cleanWs()
}
}
}
关键改动说明
| 原来(不安全) | 现在(安全) |
|---|---|
credentials('xxx') 读Jenkins内部存储 |
withSMSCredential(credentialId: 'xxx') 从SMS动态获取 |
| 密码存在Jenkins里,手动轮换 | 密码存在SMS里,自动轮换 |
| 无法追溯谁用了密码 | 每次使用都有审计日志 |

五、集成gitleaks,在提交阶段就拦截密钥泄露
光是改Jenkinsfile还不够,要在提交代码的那一刻就阻止密钥进入代码库。
安装gitleaks
# Linux
curl -sSfL https://raw.githubusercontent.com/gitleaks/gitleaks/master/scripts/install.sh | sh
# 或者下载预编译版本
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz
配置pre-commit hook
在项目根目录创建 .pre-commit-config.yaml:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
或者直接用git hook:
# .git/hooks/pre-commit
#!/bin/bash
echo "🔍 正在扫描敏感信息..."
gitleaks protect --verbose --redact --staged
if [ $? -ne 0 ]; then
echo "❌ 检测到敏感信息,提交被阻止!"
echo "请用 git reset HEAD~ 撤回,删除敏感信息后重新提交"
exit 1
fi
echo "✅ 未检测到敏感信息,允许提交"
在Jenkins流水线里也加上扫描
stage('安全扫描') {
steps {
sh '''
# 安装gitleaks
curl -sSfL https://raw.githubusercontent.com/gitleaks/gitleaks/master/scripts/install.sh | sh
# 扫描整个仓库
gitleaks detect --source . --verbose --redact
if [ $? -ne 0 ]; then
echo "❌ 代码中存在硬编码密钥,请清理后重新提交"
exit 1
fi
'''
}
}
六、改造前后对比
改造前(危险)
Jenkinsfile(改造前)
├── 密码明文出现在代码中
├── Jenkins日志里能看到密码
├── 密码长期不变(6个月+)
├── 谁用了密码完全不知道
└── 员工离职后密码依然有效
改造后(安全)
Jenkinsfile(改造后)
├── 代码中完全不出现任何明文密码
├── 构建日志自动脱敏(SMS插件自动处理)
├── 密码按TTL自动轮换(例如每24小时)
├── 每次使用都有审计日志(谁/何时/用了什么)
└── 员工离职 → 禁用AppId → 所有凭据立即失效

七、常见问题FAQ
Q:SMS Server挂了,Jenkins流水线还能跑吗?
A:SMS Jenkins插件支持本地缓存模式,Server不可用时使用上次成功获取的凭据,流水线不受影响。
Q:改造需要改多少Jenkinsfile?
A:每个Jenkinsfile平均改动3-5行,主要是把credentials()替换成withSMSCredential(),30分钟可以完成一个项目的改造。
Q:等保三级对CI/CD凭据管理有什么要求?
A:等保三级要求:1) 凭据加密存储;2) 定期轮换(≤90天);3) 访问审计;4) 最小权限原则。SMS+Jenkins插件全套满足,且有合规报告导出功能。
Q:gitleaks会不会误报?
A:会有一定误报,可以通过在项目根目录添加.gitleaksignore文件来排除特定文件或规则。
八、小结
Jenkins流水线里的明文密码,就像是把公司大门的钥匙挂在门口——不是会不会被攻击的问题,而是什么时候被攻击的问题。
通过SMS凭据管理系统 + Jenkins插件 + gitleaks扫描三层防护:
- ✅ 代码中彻底消灭硬编码密码
- ✅ 凭据按TTL自动轮换,不留死角
- ✅ 完整的审计日志,等保合规无压力
- ✅ 提交阶段就拦截,把风险消灭在上游
改造一个Jenkins项目的全部流水线,通常不超过2小时。但避免一次泄露事故,可能拯救整个团队。
如果你在做等保合规或需要国产化替代,可以了解一下安当SMS凭据管理系统。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)