1.1 为什么要使用凭据?
在我们配置持续交付流水线的过程中会与第三方的系统交互。例如:Jira、GitLab、SonarQube等等工具。平时我们在设置第三方系统的认证信息的时候是明文配置的,这样非常不安全,建议使用Jenkins凭据来存储使用。Jenkins的凭据管理是通过Credentials Binding
插件实现的,所以在使用前请确保插件已经安装了。
接下来我们演示凭据的使用:进入系统管理> 凭据管理
在这里,你将看到系统中的所有的可用的凭据,默认是空的。现实生活中我们每个人都有一个唯一的身份证号码,凭据也具有一个唯一的ID,我们后续在流水线中通过凭据的ID来读取对应的凭据。凭据ID很重要,可以自己定义。
1.2 凭据的类型
凭据其实也是可以划分多个作用域的,默认是全局作用域。我们进入全局作用域,然后可以添加凭据
。添加凭据的时候我们可以选择凭据类型、凭据内容、凭据ID、凭据描述。
Jenkins中凭据支持的类型偏多,用法都比较类似所以这里列举常用的凭据类型:
- Secret text: 存放一些API Token,类似于GitLab Personal Token等等。
- Username and password:存放用户名和密码类型的凭据,例如:GitLab管理员的账号密码。
- SSH Username with private key:存放一个SSH认证秘钥信息。
我们来创建一个Secret text
类型的凭据。这里的凭据主要用来存放第三方系统交互的API Token
。我在这里就随便写一个token 了。注意大家在写的时候要以实际为准。
变量的作用域:System
只能由Jenkins系统中访问,例如:插件。Global
是全局的在System
的基础上也可以供Job
访问。 是保存后就能看到我们的凭据了。
1.3 jenkins 如何存储凭据?
Jenkins的凭据加密存储用到了三个文件:credentials.xml
文件里面存储的是加密后的凭据。master.key
纯文本格式存储的key。hudson.util.Secret
二进制文件加密文件。(这里暂时不研究凭据的加密过程)
$JENKINS_HOME/credentials.xml $JENKINS_HOME/secrets/master.key$JENKINS_HOME/secrets/hudson.util.Secret
获取所有的凭据ID。
代码语言:javascript复制# cat credentials.xml | grep "<id>"<id>192.168.1.200-ssh-users</id><id>jenkins-ssh-user</id><id>gitlab-api-token</id>
代码语言:javascript复制<?xml version='1.1' encoding='UTF-8'?><com.cloudbees.plugins.credentials.SystemCredentialsProvider plugin="credentials@2.3.12"> <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash"> <entry> <com.cloudbees.plugins.credentials.domains.Domain> <specifications/> </com.cloudbees.plugins.credentials.domains.Domain> <java.util.concurrent.CopyOnWriteArrayList> .........
<org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl plugin="plain-credentials@1.7"> <scope>GLOBAL</scope> <id>gitlab-api-token</id> <description>gitlab-api-token</description> <secret>{AQAAABAAAAAQkZVQA/LNTRYnWBibiMI4hFjO2HcNNME8jkDLA/kGVEc=}</secret> </org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl> ........... </java.util.concurrent.CopyOnWriteArrayList> </entry> </domainCredentialsMap></com.cloudbees.plugins.credentials.SystemCredentialsProvider>
凭据内容是加密的,如果忘记了怎么办呢?我们具有管理员权限是可以根据secret
解密的。这里简单演示一下,我通常如果忘记了凭据的内容,我会这样做的。在Script Console
,输入一下语句。
println hudson.util.Secret.decrypt("{AQAAABAAAAAQkZVQA/LNTRYnWBibiMI4hFjO2HcNNME8jkDLA/kGVEc=}")
如果你想把所有的凭据内容解密,推荐可以使用工具jenkins-credentials-decryptor
解密。此工具的项目地址:https://github.com/hoto/jenkins-credentials-decryptor/releases/download/0.0.8/jenkins-credentials-decryptor_0.0.8_Linux_x86_64
cd ${JENKINS_HOME}
mv jenkins-credentials-decryptor_0.0.8_Linux_x86_64 jenkins-credentials-decryptor
chmod x jenkins-credentials-decryptor
./jenkins-credentials-decryptor
-m ./secrets/master.key
-s ./secrets/hudson.util.Secret
-c ./credentials.xml
##### 输入#######3
0
scope=GLOBAL
id=192.168.1.200-ssh-users
description=192.168.1.200-ssh-users
username=root
password=123456
1
privateKeySource=
scope=GLOBAL
id=jenkins-ssh-user
description=jenkins-ssh-user
username=root
2
scope=GLOBAL
id=gitlab-api-token
description=gitlab-api-token
secret=aaaaaabbbbbbb
1.4 项目中使用凭据
为了最大程度地提高安全性,在Jenkins中配置的凭据以加密形式存储在主Jenkins实例上(由Jenkins实例ID加密),并且仅在Pipeline项目中通过其凭据ID进行使用。这最大程度地减少了将实际凭证本身暴露给Jenkins用户的机会。
在涉及到代码下载的时候需要用到凭据
在参数化构建项目中添加凭据参数
Credentials As Code
由于我们目前还没有学习到Jenkins pipeline项目,所以这里先做为了解,后续对你一定有用的。我们先随便创建一个流水线
类型的项目。然后选择流水线语法
, 进入片段生成器
。
点击新增
,选择要使用的凭据。这种情况我们是把凭据作为值赋给了变量,所以在这里定义一个变量名称,然后后续在流水线中使用此变量引用凭据的内容。
选择好凭据之后,我们开始点击生成流水线脚本
。最后生成了如下的代码块。some block
是一些语句块。
withCredentials([string(credentialsId: 'gitlab-api-token', variable: 'gitUsers')]) { // some block}
好了,现在基本上你已经掌握了如何生成凭据代码块。接下来我们写个简单的demo来测试一下。这个模板是通用的,可以复制哦。
代码语言:javascript复制pipeline { agent any
stages { stage('Hello') { steps { echo 'Hello World' withCredentials([string(credentialsId: 'gitlab-api-token', variable: 'gitUsers')]) { // some block println(gitUsers)} } } }}
运行作业,检查日志会发现Jenkins试图通过查找密钥值并将其替换为星号来从构建日志中显示。
这里注意下,我们以使用变量的方式打印它们,便可以看到实际的秘密值。这样,每个字符将单独打印。所以这里要严格把控流水线的编辑权限,否则还是会造成秘钥泄露。
代码语言:javascript复制print 'gitUsers.collect { it }=' gitUsers.collect { it }
这里我们来展示一个操作GitLab系统的参考实例,这个实例就是后续我们在共享库中定义的内容。
代码语言:javascript复制//封装HTTP请求def HttpReq(reqType,reqUrl,reqBody){ def gitServer = "http://192.168.1.200:30088/api/v4" withCredentials([string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) { result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]], httpMode: reqType, contentType: "APPLICATION_JSON", consoleLogResponseBody: true, ignoreSslErrors: true, requestBody: reqBody, url: "${gitServer}/${reqUrl}" //quiet: true } return result}
今天我们分享了Jenkins的凭据管理,通过凭据管理可以对流水线中与第三方系统交互需要配置的认证信息加密存储。便于对流水线中数据脱敏。但是jenkins的凭据管理还是存在一些安全漏洞问题,如果允许最好将秘钥信息存储在外围系统中。我们不创建秘密,它们就不会泄漏。后续我们继续分享Jenkins系统中的权限管理。