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-readonlydocker-registry-pushk8s-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)练习#

  1. 创建git-prod-readonly凭据并在Pipeline中使用SSH拉取代码。
  2. dev命名空间创建jenkins-deployer并限制仅能更新Deployment。
  3. 编写Pipeline完成镜像构建与推送,确保docker logout被执行。
  4. 模拟凭据失效,观察失败日志并完成轮换恢复。