18.7.4 凭据管理与安全实践
4. 凭据管理与安全实践#
凭据管理是Jenkins与Git、Docker、Kubernetes集成的安全基础。本节覆盖凭据体系、最小权限、密钥生命周期、审计与排错,提供可执行示例与练习。
原理草图:凭据流转与最小权限
1)Jenkins凭据体系与类型选择(含安装与配置)#
安装凭据相关插件(示例)
- 建议安装:Credentials Binding、Mask Passwords、Kubernetes CLI、Git、Docker Pipeline
# 通过Jenkins CLI安装插件(示例)
# 需先在“系统管理-管理Jenkins-CLI”开启并下载jenkins-cli.jar
java -jar jenkins-cli.jar -s http://jenkins.local:8080/ -auth admin:admin \
install-plugin credentials-binding mask-passwords git docker-workflow kubernetes-cli
# 重启生效
java -jar jenkins-cli.jar -s http://jenkins.local:8080/ -auth admin:admin safe-restart
凭据类型建议
- Git:SSH私钥或Personal Access Token(只读)
- Docker Registry:用户名/密码或Token(限定仓库)
- Kubernetes:Kubeconfig或ServiceAccount Token(最小RBAC)
创建凭据(UI路径)
- 系统管理 → 凭据 → (全局/系统/Folder域) → 添加凭据
- 命名规范:git-prod-readonly、docker-registry-push、k8s-dev-sa
2)流水线中的安全使用(示例与命令解释)#
Pipeline示例:避免密钥泄露
pipeline {
agent any
stages {
stage('Git Checkout') {
steps {
withCredentials([sshUserPrivateKey(
credentialsId: 'git-prod-readonly',
keyFileVariable: 'GIT_KEY',
usernameVariable: 'GIT_USER'
)]) {
sh '''
# 使用GIT_SSH_COMMAND传入临时私钥文件
export GIT_SSH_COMMAND="ssh -i $GIT_KEY -o StrictHostKeyChecking=no"
git clone git@github.com:org/repo.git
'''
}
}
}
}
}
命令解释
- withCredentials:在闭包中注入临时环境变量
- ssh -i $GIT_KEY:使用临时文件传递密钥,避免命令行明文
3)与Git集成安全实践(示例+排错)#
Webhook签名校验(GitHub示例)
// Jenkinsfile片段(使用Generic Webhook Trigger插件时)
if (!env.GITHUB_WEBHOOK_SECRET) {
error "Webhook Secret not set"
}
排错思路
- 触发失败:检查Webhook地址、Secret是否一致、Jenkins日志 /var/log/jenkins/jenkins.log
- 拉取失败:检查SSH私钥权限、部署Key是否只读、仓库访问权限
4)与Docker集成安全实践(示例+命令)#
安全登录与推送
pipeline {
agent any
environment {
REGISTRY = "registry.example.com"
IMAGE = "registry.example.com/app:${BUILD_NUMBER}"
}
stages {
stage('Build & Push') {
steps {
withCredentials([usernamePassword(
credentialsId: 'docker-registry-push',
usernameVariable: 'REG_USER',
passwordVariable: 'REG_PASS'
)]) {
sh '''
echo "$REG_PASS" | docker login $REGISTRY -u "$REG_USER" --password-stdin
docker build -t $IMAGE .
docker push $IMAGE
docker logout $REGISTRY
'''
}
}
}
}
}
命令解释
- docker login --password-stdin:避免明文泄露
- docker logout:构建后清理登录态
排错
- denied: requested access to the resource is denied:凭据权限不足或仓库不存在
- unauthorized: authentication required:检查凭据ID和Registry地址
5)与Kubernetes集成安全实践(示例+RBAC)#
为Jenkins创建最小权限ServiceAccount
# 文件:k8s/jenkins-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-deployer
namespace: dev
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jenkins-deploy-role
namespace: dev
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get","list","watch","create","update","patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins-deploy-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: jenkins-deployer
namespace: dev
roleRef:
kind: Role
name: jenkins-deploy-role
apiGroup: rbac.authorization.k8s.io
# 创建SA与权限
kubectl apply -f k8s/jenkins-sa.yaml
Kubeconfig创建与凭据保存
# 获取ServiceAccount的token
kubectl -n dev get secret $(kubectl -n dev get sa jenkins-deployer -o jsonpath="{.secrets[0].name}") \
-o jsonpath="{.data.token}" | base64 -d
# 构建最小Kubeconfig(示例)
cat > /tmp/jenkins-kubeconfig <<'EOF'
apiVersion: v1
kind: Config
clusters:
- name: dev-cluster
cluster:
server: https://k8s.example.com:6443
insecure-skip-tls-verify: true
users:
- name: jenkins
user:
token: REPLACE_TOKEN
contexts:
- name: dev
context:
cluster: dev-cluster
user: jenkins
namespace: dev
current-context: dev
EOF
Pipeline部署示例
stage('Deploy to K8s') {
steps {
withCredentials([file(credentialsId: 'k8s-dev-kubeconfig', variable: 'KUBECONFIG')]) {
sh '''
kubectl --kubeconfig=$KUBECONFIG apply -f k8s/deploy.yaml
kubectl --kubeconfig=$KUBECONFIG rollout status deploy/myapp -n dev
'''
}
}
}
排错
- Forbidden:RBAC权限不足,检查Role/RoleBinding
- Unable to connect to the server:API地址或网络问题
6)凭据轮换与审计(示例+命令)#
轮换流程建议
1. 在Jenkins新增新凭据(新Token/新密钥)
2. 修改Pipeline凭据ID
3. 执行试运行
4. 删除旧凭据
审计与日志
- 启用审计插件或查看系统日志 /var/log/jenkins/jenkins.log
- 配置敏感信息遮罩(Mask Passwords)
7)对接外部密钥管理(示例)#
Vault动态凭据(示例流程)
- Jenkins仅请求短期Token,减少泄露风险
stage('Get Secret from Vault') {
steps {
withVault([vaultSecrets: [[path: 'secret/data/git', secretValues: [[envVar: 'GIT_TOKEN', vaultKey: 'token']]]]]) {
sh 'echo "Got token from Vault (masked)"'
}
}
}
8)常见风险与处置建议(含排错)#
| 风险 | 现象 | 处置 |
|---|---|---|
| 明文泄露 | 控制台输出Token | 吊销密钥、清理日志、限制echo |
| 权限过大 | 操作非目标命名空间 | 调整RBAC、分环境凭据 |
| 凭据失效 | 构建/部署失败 | 到期预警、自动轮换 |
9)练习#
- 创建
git-prod-readonly凭据并在Pipeline中使用SSH拉取代码。 - 为
dev命名空间创建jenkins-deployer并限制仅能更新Deployment。 - 编写Pipeline完成镜像构建与推送,确保
docker logout被执行。 - 模拟凭据失效,观察失败日志并完成轮换恢复。