凭据管理

Jenkins 凭据概述

Jenkins 凭据是 Jenkins 中用于安全存储和管理敏感信息的机制。这些凭据可以用来提供给 Jenkins 作业、管道(pipeline)或插件,避免在脚本中硬编码敏感信息,如密码、SSH 密钥、API 令牌等。Jenkins 凭据的设计使得用户可以安全地处理这些信息,且通过访问控制保证只有经过授权的任务和人员能够使用它们。

凭据的主要类型

Jenkins 支持多种类型的凭据,常见的有:

  1. 用户名和密码(Username with password)

    • 这是最基本的凭据类型,存储用户名和密码,通常用于 HTTP 基本认证、API 访问等。
  2. SSH 私钥(SSH Username with private key)

    • 用于 SSH 连接时的认证,通常在 Jenkins 中执行 SSH 操作(如通过 SSH 连接到远程主机)时使用。
  3. Secret Text

    • 单个的密文字符串,可以是密码、API 令牌或其他类型的密钥。常用于与第三方服务集成时提供 API Token。
  4. Secret File

    • 敏感的文件凭据,比如私钥文件、配置文件等,可以在作业中下载并使用。
  5. 证书(Certificate)

    • 用于存储包含私钥的证书文件,通常用于需要双向 SSL 的场景,如与某些服务的加密通信。
  6. GitHub 凭据

    • 专用于 GitHub 操作的 OAuth 令牌、用户名/密码或 SSH 私钥,用于与 GitHub 仓库交互。

Jenkins 中的凭据存储

Jenkins 凭据默认存储在主控节点的加密数据库中。Jenkins 通过 Credentials 插件来管理凭据,并通过 Web 界面或 Jenkinsfile 进行使用和引用。对于安全性,Jenkins 采用两种机制来保护凭据:

  1. 凭据域(Credential Domains)

    • 可以将不同的凭据分配到不同的域中,限制它们在哪些 Jenkins 作业或项目中可用。例如,你可以创建一个用于生产环境的凭据域,确保这些凭据只能用于生产相关的作业,而无法被其他作业访问。
  2. 凭据作用范围(Scope)

    • 凭据可以设置为 全局系统范围,全局凭据可在 Jenkins 实例中的所有项目使用,而系统范围的凭据仅限于特定的 Jenkins 系统组件。

凭据使用示例

  1. 在 Jenkins 界面中使用:

    • 在配置 Jenkins 任务时,可以在 “构建环境” 或 “源码管理” 中引用存储的凭据。例如,配置 Git SCM 时,可以选择一个存储的凭据来访问 Git 仓库。
  2. 在 Jenkinsfile 中使用:

    • 在 pipeline 脚本中,使用 credentials 函数来引用凭据,例如:

      pipeline {
          agent any
          stages {
              stage('Build') {
                  steps {
                      withCredentials([usernamePassword(credentialsId: 'my-credentials-id', usernameVariable: 'USER', passwordVariable: 'PASS')]) {
                          sh 'echo "Using username $USER and password $PASS"'
                      }
                  }
              }
          }
      }

在这个例子中,凭据 ID 为 my-credentials-id 的用户名和密码被赋值给环境变量 USERPASS,可以在 Shell 脚本中引用。

安全注意事项

  • 最小化凭据访问权限:使用凭据域和作用范围,确保凭据只对需要的作业和用户可见。
  • 审计和监控:定期检查哪些凭据被访问,并通过 Jenkins 的审计插件跟踪谁使用了哪些凭据。
  • 密钥轮换:定期更新凭据,避免长期使用相同的密钥或密码。

通过合理配置 Jenkins 凭据系统,能够提高敏感信息的安全性并减少泄露的风险。

Jenkins 添加凭据

GitLab

在 Jenkins 中添加并使用 GitLab 个人访问令牌(Personal Access Token, PAT)作为凭据,可以让 Jenkins 自动访问 GitLab 仓库,执行构建、触发 CI/CD 管道等操作。以下是详细步骤:

一、在 GitLab 中生成个人访问令牌(PAT)

  1. 登录到 GitLab
    • 使用你的 GitLab 账号登录到 GitLab 实例。
  2. 进入个人设置
    • 点击右上角的头像,选择 Settings(设置)
  3. 访问 Token 配置
    • 在左侧菜单中,找到 Access TokensPersonal Access Tokens 选项。
  4. 生成新的 Token
    • 在创建页面中,输入令牌的名称(如 Jenkins Token)。
    • 设置有效期(可选,如果你希望令牌有过期时间)。
    • 选择适当的 权限范围(Scopes),一般需要勾选:
      • api:允许 Jenkins 访问 GitLab API。
      • read_user:读取用户信息。
      • read_repositorywrite_repository:访问 Git 仓库(write_repository 允许推送代码)。
  5. 创建并保存
    • 点击 Create personal access token,GitLab 会生成一个新的 Token。
    • 注意:生成的 Token 只会显示一次,请记得保存到安全的地方。
    • glpat-FPsLWNSZxss-xGxX5WXh
  6. 测试 Token:
    • git clone https://<ACCESS_TOKEN_NAME>:<YOUR_ACCESS_TOKEN>@gitlab.com/<USERNAME>/<REPOSITORY>.git
    • git clone http://cicd:glpat-FPsLWNSZxss-xGxX5WXh@172.16.20.24/four_honey/front.git

二、在 Jenkins 中添加 GitLab 个人令牌作为凭据

  1. 进入 Jenkins 管理界面

    • 打开 Jenkins 的 Web 界面,点击左侧菜单的 Manage Jenkins
  2. 打开凭据管理

    • Manage Jenkins 页面,选择 Manage Credentials
  3. 选择存储域

    • 选择要存储凭据的域(通常为 Global domain,表示全局可用)。
    • 点击 (global) 右侧的 Add Credentials 按钮。
  4. 添加新凭据: 在添加凭据的页面中,完成以下配置:

    • Kind:选择 Secret text(因为 GitLab 的 PAT 是一个纯文本的密钥)。
    • Secret:将你从 GitLab 获取的个人访问令牌粘贴到这里。
    • ID(可选):为该凭据设置一个唯一的 ID(如 gitlab-pat),方便在 Jenkinsfile 或作业中引用。
    • Description:为凭据添加描述(如 GitLab Personal Access Token for Jenkins)。
  5. 保存凭据

    • 点击 OK,保存此凭据。

三、在 Jenkins 中使用 GitLab 个人令牌

凭据添加完成后,你可以在 Jenkins 中的作业或管道中使用它。

1. 在传统 Jenkins Freestyle 作业中使用

  • 在配置 Freestyle 项目时,设置 GitGitLab SCM(Source Code Management)插件。
  • Credentials 下拉框中,选择之前添加的 GitLab 个人访问令牌(PAT)凭据。
  • 这样,Jenkins 就可以使用该 Token 拉取 GitLab 仓库代码了。

2. 在 Pipeline 脚本中使用

Jenkinsfile 中,通过 withCredentials 函数引用这个凭据,例如:

pipeline {
    agent any
    stages {
        stage('Clone GitLab Repo') {
            steps {
                withCredentials([string(credentialsId: 'gitlab-pat', variable: 'GITLAB_TOKEN')]) {
                    sh 'git clone https://gitlab-ci-token:$GITLAB_TOKEN@gitlab.com/username/repo.git'
                }
            }
        }
    }
}

在此例中:

  • 使用 withCredentials 将凭据 ID 为 gitlab-pat 的令牌赋值给环境变量 GITLAB_TOKEN
  • sh 步骤中使用 git clone 命令,从 GitLab 上克隆仓库。

3. 使用 Jenkins GitLab Plugin

  • 如果你使用的是 Jenkins 的 GitLab 插件,可以直接在插件配置中选择凭据。大多数 GitLab 插件,如 GitLab Branch Source PluginGitLab Authentication Plugin,支持选择 Jenkins 的凭据进行身份验证。

总结

  1. 生成 GitLab 个人访问令牌(PAT),确保拥有正确的访问权限范围(如 apiread_repository 等)。
  2. 在 Jenkins 中添加该令牌为 Secret text 类型的凭据
  3. 在 Freestyle 作业或 Pipeline 中使用凭据,通过 withCredentials 引用 Token,安全地进行 GitLab 操作。

这样配置完成后,Jenkins 就可以通过安全的方式访问 GitLab 仓库进行各种自动化操作了。

SSH 私钥

在 Jenkins 中添加和使用 SSH 私钥作为凭据,可以让 Jenkins 安全地通过 SSH 访问远程服务器或 Git 仓库。以下是详细步骤,包括如何添加 SSH 私钥凭据以及如何在 Jenkins 作业和管道(Pipeline)中使用它。

一、生成 SSH 私钥(如果还没有)

如果你还没有 SSH 私钥,可以在你的机器上生成一个新的私钥。

  1. 在本地生成 SSH 密钥对

    在被连接的主机中,使用以下命令生成 SSH 密钥对:

    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    • -t rsa:指定使用 RSA 算法生成密钥。
    • -b 4096:密钥长度为 4096 位。
    • -C:注释,可填入你的邮箱或描述信息。

    生成后,密钥文件通常位于 ~/.ssh/ 目录下,其中 id_rsa 是私钥,id_rsa.pub 是公钥。

  2. 将公钥添加到远程服务器或 Git 仓库

    • 如果要通过 SSH 访问 Git 仓库(如 GitHub、GitLab),需要将 id_rsa.pub 添加到你的 Git 仓库的 SSH keys 配置页面。
    • 如果要通过 SSH 访问服务器,需要将 id_rsa.pub 添加到远程服务器的 ~/.ssh/authorized_keys 文件中。

二、在 Jenkins 中添加 SSH 私钥凭据

  1. 进入 Jenkins 管理界面

    • 打开 Jenkins 的 Web 界面,点击左侧的 Manage Jenkins
  2. 打开凭据管理

    • Manage Jenkins 页面,选择 Manage Credentials
  3. 选择存储域

    • 选择要存储凭据的域,通常为 Global,表示全局可用。
    • 点击 (global) 右侧的 Add Credentials 按钮。
  4. 添加 SSH 凭据

    在添加凭据的页面中,完成以下配置:

    • Kind:选择 SSH Username with private key
    • Scope:选择凭据的作用范围,可以选择全局(Global)或系统范围(System)。
    • Username:输入与你的 SSH 私钥相关联的用户名(通常是远程服务器的用户名,或 Git 仓库的用户名)。
    • Private Key:选择 Enter directly,然后粘贴你本地 id_rsa 文件中的内容(不要包含 .pub 公钥,只粘贴私钥部分)。
      • 如果你的私钥有密码,可以勾选 Passphrase,并输入密码。
    • ID(可选):为该凭据设置一个唯一的 ID(如 my-ssh-key),方便在 Jenkinsfile 或作业中引用。
    • Description:为凭据添加描述(如 SSH Key for GitHub)。
  5. 保存凭据

    • 点击 OK,保存此 SSH 凭据。

三、在 Jenkins 中使用 SSH 私钥

1. 在 Freestyle 作业中使用

  • 在配置 Freestyle 作业时,可以通过 GitSSH 相关插件,使用 SSH 凭据。

    • 如果使用 Git SCM,选择 Git 作为源代码管理工具。
    • Credentials 下拉列表中,选择你刚才添加的 SSH 私钥凭据。

这样 Jenkins 就可以使用 SSH 私钥从 Git 仓库克隆代码了。

2. 在 Pipeline(Jenkinsfile)中使用

Jenkinsfile 中,使用 withCredentials 函数来引用 SSH 私钥。例如:

pipeline {
    agent any
    stages {
        stage('Clone with SSH') {
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: 'my-ssh-key', keyFileVariable: 'SSH_KEY', usernameVariable: 'USER')]) {
                    sh '''
                    echo "Cloning repository using SSH"
                    GIT_SSH_COMMAND="ssh -i $SSH_KEY" git clone git@github.com:your-repo/your-project.git
                    '''
                }
            }
        }
    }
}

在这个例子中:

  • credentialsId: 'my-ssh-key' 指的是你在 Jenkins 中添加的 SSH 私钥凭据的 ID。
  • keyFileVariable: 'SSH_KEY' 是 Jenkins 在运行时将 SSH 私钥内容保存到的环境变量。
  • usernameVariable: 'USER' 是将用户名保存到的环境变量。
  • GIT_SSH_COMMAND="ssh -i $SSH_KEY" 使用了 SSH 私钥来执行 git clone 操作。

四、使用 SSH 凭据

通过 SSH Agent 插件

https://www.jenkins.io/doc/pipeline/steps/ssh-agent/

https://plugins.jenkins.io/ssh-agent/

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                echo 'Deploying to Nginx server...'
                sshagent (credentials: ['ssh_key-172.16.0.123']) {
                    sh 'scp -r -o StrictHostKeyChecking=no * root@172.16.0.123:'
                     sh 'ssh -o StrictHostKeyChecking=no root@172.16.0.123 uname -a'
                }
            }
        }
    }
}

通过 Git 插件

  1. Jenkins Git Plugin

    如果你使用 Git 插件来从 Git 仓库拉取代码,Git 插件会自动检测并支持使用 SSH 凭据。只需在配置源码管理时,选择对应的凭据即可。

  2. Jenkins SSH Agent Plugin

    在需要通过 SSH 连接远程服务器时,可以使用 SSH Agent Plugin,该插件允许你在构建期间使用 SSH 凭据。以下是一个 Pipeline 使用 ssh-agent 插件的例子:

    pipeline {
        agent any
        stages {
            stage('SSH to Remote Server') {
                steps {
                    sshagent(['my-ssh-key']) {
                        sh 'ssh -o StrictHostKeyChecking=no user@remote-host "ls -la"'
                    }
                }
            }
        }
    }

    在这个例子中:

    • sshagent(['my-ssh-key']):启动 SSH Agent,并加载 Jenkins 中 ID 为 my-ssh-key 的 SSH 凭据。
    • sh 'ssh ...':通过 SSH 连接到远程服务器,并执行命令。

总结

  1. 生成 SSH 私钥:如果没有 SSH 私钥,首先在本地生成一个。
  2. 添加 SSH 私钥到 Jenkins:在 Jenkins 中通过 SSH Username with private key 类型添加 SSH 凭据,粘贴私钥,并配置相关参数。
  3. 在作业或 Pipeline 中使用 SSH 凭据:通过 Jenkins 的 Git 插件、withCredentials 函数,或使用 ssh-agent 插件来安全地使用 SSH 凭据进行 Git 操作或连接远程服务器。

通过这些步骤,你可以安全地使用 SSH 凭据来进行自动化的操作。

Credential 概述

https://www.jenkins.io/zh/doc/book/using/using-credentials/

https://www.jenkins.io/doc/book/using/using-credentials/

  • 有时候,我们需要在Pipeline中为steps提供凭证,以完成steps中必要的操作步骤,从而避免将敏感信息直接写入pipeline中;
    • 例如:当gitlab需要基于ssh协议拉取代码时,就可以配置一个ssh的凭据,最后在pipeline中引用

Credential 类型

Jenkins 支持的凭据包括但不限于以下类型,取决于安装的插件

  • 例如:二进制数据,或者更复杂形式的项目,例如OAuth凭据等;

Username with password:用户名和密码,

Github App

SSH Username with private key:SSH用户名和私钥

Secret file:需要保密的文本文件,保存有Token等信息

Secret text:Token,一串需要保密的文本,例如Github的API Token等;

Certificate:证书

Gitlab API Token:安装 Gitlab 插件后生成的凭据类型

Credential 作用域

凭据的作用域决定了它可用的目标范围;

  • 系统:作用于Jenkins系统自身,仅可用于系统和后台任务,且一般用于连接到agent节点之上;
  • 全局:作用于Jenkins上的所有任务,以确保任务的正常执行;
  • 用户:作用于用户级别,仅生效于Jenkins中的线程代表该用户进行身份验证之时;

Credential 提供者

凭据Provider是指能够存储和获取凭据的地方,它可以Jenkins内部的凭据存储,也可以是外部的凭据库例如:vault

Jenkins共支持如下几个凭据Provider

  • 系统凭据Provider:支持系统和全局两个作用域的凭据;
  • 用户凭据Provider:用户凭据的存储机制,且每个用户仅能看到自己的凭据;
  • 文件夹凭据Provider:文件夹凭据存储,可作用于该文件夹及其子文件夹;
    • 默认存放在$Jenkins_HOME/secrets 目录下,默认该目录的权限为700,为了安全起见,目录的权限一定要保持正确
  • Blue Ocean凭据插件:作用于Blue Ocean接口,以及通过该接口创建或访问的项目;

Credential 配置

系统管理 –> 凭据配置,Jenkins的凭据配置用于定义凭据的提供者和类型

  • 提供者:
    • 包括选择:明确选定要使用的凭证提供者
    • 所有可见
    • 排除选择:明确排除不支持使用的凭证提供者
  • 类型:
    • 包括选择:明确选定要使用的凭证类型
    • 所有可见
    • 排除选择:明确排除不支持使用的凭证类型

Credential 创建

  • ID:如未指定则会生成一个随机ID,通常明确指定ID名称 以便于在pipeline中引用。

Credential Plugin

Credential Binding

https://plugins.jenkins.io/credentials-binding/

https://docs.cloudbees.com/docs/cloudbees-ci/latest/cloud-secure-guide/injecting-secrets

https://docs.cloudbees.com/docs/cloudbees-ci/latest/cloud-secure-guide/injecting-secrets

  • 凭据绑定插件,可以实现将凭据绑定到环境变量中,而后可以在steps中引用,该插件默认已经安装;

  • 相关语法可以参考片断生成器中的 withCredentials: Bind credentials to variables

    • 以Username and password举例:

      • Username and password (separated)

      • 用户名变量,例如:USERNAME

      • 密码变量,例如:PASSWORD

      • 凭据,选择先决条件中创建的凭据

Username with password

  • 需要先创建一个 Username with password 类型的 Credential
// 用户名和密码使用变量名可自行指定,而后,Jenkins都会通过credentialsID从指定的凭证填充用户名和密码
// 最后在控制台的输出结果为USERNAME会正常打印,PASSWORD由于默认加密所以输出结果为*****
pipeline {
    agent any 
    stages {
        stage('Test Credentials') {
            steps {
                withCredentials([usernamePassword(credentialsId: 'azheng-user', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) { // 需要进行的操作定义在{}中
                    echo "$USERNAME" // 使用pipeline内置echo时建议使用双引号
                    sh 'echo $PASSWORD' // 调用shell插件时建议使用单引号
                } 
            }
        }
    }
}

SSH Agent

https://plugins.jenkins.io/ssh-agent/

  • 该插件可以实现在pipeline中添加ssh私钥凭据
    • 请注意,只能使用基于私钥的凭据。

先决条件

  • 创建ssh私钥的凭据

pipeline example

  • 相关语法可以参考片断生成器中的 SSHAGENT: SSH Agent

1

  • 有待验证
pipeline {
    agent any 
    stages {
        stage('Update Source') {
            steps {
                sshagent(['ssh-private-key-gitlab-user-magedu']) {
                    sh 'git config user.name iKubernetes'
                    sh 'git config user.email mage@magedu.com'
                    sh "git tag –a ${env.BUILD_TAG} –m 'iKubernetes push of tags'"
                    sh "git push ${sshRepodef} –tags"
                }
            }
        }
    }
}

2

steps {
    sshagent(credentials: ['ssh-credentials-id']) {
      sh '''
          [ -d ~/.ssh ] || mkdir ~/.ssh && chmod 0700 ~/.ssh
          ssh-keyscan -t rsa,dsa example.com >> ~/.ssh/known_hosts
          ssh user@example.com ...
      '''
    }
}

优雅地使用凭证

  • 显然,每次调用凭证时都使用withCredentials( )有点过于麻烦;
  • 为此,声明式pipeline提供了 credentials helper方法,它允许在environment{}代码段中通过credentials(‘credentialsId’)直接取出凭证并保存于指定的变量中;
pipeline {
    agent any
    environment {
        ding_robot_token = credentials('dingtalk-robot-token')
    }
    stages {
        stage('debug') {
            steps {
                sh "printenv"
            }
        }
    }
    post {
        success {
            script {
                echo "${env.ding_robot_token}"
            }
            dingTalk accessToken: "${env.ding_robot_token}", imageUrl: '', jenkinsUrl: '', message: 'Build  Successfully.', notifyPeople: ''
        }
    }
}