jenkins06-凭证管理
1、凭证管理介绍
1、为什么要管理凭证
- 众所周知,在Jenkinsfile或部署脚本中使用明文密码会造成安全隐患。但是为什么还频繁出现明文密码被上传到GitHub上的情况呢?笔者认为有两个主要原因(当然,现实的原因可能更多):
- (1)程序员或运维人员不知道如何保护密码。
- (2)管理者没有足够重视,否则会给更多的时间让程序员或运维人员想办法隐藏明文密码。
2、凭证是什么
- 凭证(cridential)是Jenkins进行受限操作时的凭据。比如使用SSH登录远程机器时,用户名和密码或SSH key就是凭证。而这些凭证不可能以明文写在Jenkinsfile中。Jenkins凭证管理指的就是对这些凭证进行管理。
- 凭证可以用来存储需要密文保护的数据库密码、Gitlab密码、Docker私有仓库密码等,以便Jenkins可以和这些应用进行交互。
- 为了最大限度地提高安全性,在Jenkins master节点上对凭证进行加密存储(通过Jenkins实例ID加密),只有通过凭证ID才能在pipeline中使用,并且限制了将证书从一个Jenkins实例复制到另一个Jenkins实例的能力。
- 因为所有的凭证都被存储在Jenkins master上,所以在Jenkins master上最好不要执行任务,以免被pipeline非法读取出来。那么在哪里执行pipeline呢?应该分配到Jenkins agent上执行。
2、创建凭证
2.1、安装插件
- 可以使用"Credentials Binding"插件来管理Jenkins的凭证。
- 安装插件后可以在"Jenkins --> Manage Jenkins"中看到多了两个选项。
2.2、创建凭证
- 在创建凭证前,请确保当前用户有添加凭证的权限。
- Jenkins --> Manage Jenkins --> Manage Credentials --> Stores scoped to Jenkins:[Jenkins] --> 全局凭证 (unrestricted) --> Add Credentials
- Kind:选择凭证类型。
- Username with password:用户名和密码
- SSH Username with private key:使用SSH用户的公私密钥。使用时Jenkins会将SSH key复制到一个临时目录中,再将文件路径设置到一个变量中。
- Secret text:需要保存的一个加密的文本串,如钉钉机器人或Github的API token。
- Secret file:需要保密的文本文件。使用时Jenkins会将文件复制到一个临时目录中,再将文件路径设置到一个变量中,等构建结束后就会被删除。
- Certificate:通过上传证书文件的方式。
- Scope:凭证的作用域。有两种作用域:
- Global,全局作用域。如果凭证用于pipeline,则使用此种作用域。
- System,如果凭证用于Jenkins本身的系统管理,例如电子邮件身份验证、代理连接等,则使用此种作用域。
- ID:在pipeline使用凭证的唯一标识。
- 将凭证绑定到变量
- 方法一:添加凭证后,安装Credentials Binding Plugin(credentials-binding)插件,通过其提供的withCredentials步骤就可以在pipeline中使用凭证了。
- 方法二:声明式pipeline提供了credentials helper方法(只能在environment指令中使用)来简化凭证的使用。比方法一简明。
1 2 3 4 5 6 7 8 9 | //方法一 withCredentials([usernameColonPassword(credentialsId: '18729147-da8c-49c5-8573-4bdb05984519' , variable: 'BITBUCKET_CREDS' )]) { echo "${BITBUCKET_CREDS} } //方法二 environment { BITBUCKET_CREDS = credentials( '18729147-da8c-49c5-8573-4bdb05984519' ) } |
3、使用HashiCorp Vault插件管理凭证
- 如果觉得Jenkins的凭证管理功能太弱,无法满足你的需求,则可以考虑使用HashiCorp Vault。
- HashiCorp Vault是一款对敏感信息(密码、token、密钥等)进行存储,并进行访问控制的工具。它不仅可以存储敏感信息,还具有滚动更新、审计等功能。
- HashiCorp Vault插件并没有提供pipeline步骤,提供此步骤的是Hashicorp Vault Pipeline 插件。
- 但是它依赖的是2.138.1或以上的Jenkins版本。如果你的Jenkins版本低于2.138.1,但是又想用Hashicorp Vault Pipeline插件,可以将该插件的源码下载到本地,将pom.xml中的jenkins.version值从2.138.1修改成你的Jenkins版本,然后运行mvn clean package进行编译打包。如果没有报错, 则接着找到target/hashicorp-vaultpipeline.hpi进行手动安装即可。
4、在Jenkins日志中隐藏敏感信息
4.1、使用credentials helper方法或者withCredentials步骤
- 如果使用的是credentials helper方法或者withCredentials步骤为变量赋值的,那么这个变量的值是不会被明文打印到Jenkins日志中的。除非使用以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | pipeline { agent any stages { stage( 'Hidden information' ) { steps { script { def user //定义变量,变量的作用域是script{} def passwd //定义变量 withCredentials([usernamePassword(credentialsId: '18729147-da8c-49c5-8573-4bdb05984519' , passwordVariable: 'passwdValue' , usernameVariable: 'userValue' )]) { echo "${userValue}" //输出的是密文:**** echo "${passwdValue}" //输出的是密文:**** user = "${userValue}" passwd = "${passwdValue}" echo "${user}" //输出的是密文:**** echo "${passwd}" //输出的是密文:**** } echo "${user}" //输出的是明文:user01 echo "${passwd}" //输出的是明文:user01123 } } } } } |
4.2、使用Masked Pass-word插件
- 在没有使用credential的场景中,可以使用Masked Pass-word(mask-passwords)插件在日志中隐藏变量。
- 通过该插件提供的包装器,可以隐藏指定的敏感信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //该示例会抛出一个异常:java.lang.IllegalStateException: wrap step must be called with a body pipeline { agent any environment { SECRET1 = "secret1" SECRET2 = "secret2" NOT_SECRET1 = "not secret" } stages { stage( "read vault key" ) { steps { wrap(maskPasswords(varPasswordPairs: [ [password: 'secret1' , var : 's1' ], [password: 'secret2' , var : 's2' ] ]){ echo "${SECRET1}" //输出的是密文 echo "${SECRET2}" //输出的是密文 echo "secret1" //输出的是密文 echo "${NOT_SECRET1}" //输出的是明文 } ) } } } } |
- 初次使用Masked Password插件很容易以为是使用s1和s2作为变量的,如 echo "{s2}"。实际上,var参数只是用于方便在自由风格的Jenkins项目中区分不同的需要隐藏的密文。在pipeline中使用,它就没有存在的意义了。但是即使这样也不能省略它,必须传一个值。password参数传的是真正要隐藏的密文。
- 为什么echo "secret1"这条语句中并没有使用预定义的变量,也会被隐藏呢?这是由Masked Password插件的实现方式决定的。
- Jenkins提供了ConsoleLogFilter接口,可以在日志打印阶段实现我们自己的业务逻辑。Masked Password插件实现了ConsoleLogFilter接口,然后利用正则表达式将匹配到的文本replaceAll成********。
- MaskPasswordsBuildWrapper包装器除了支持varPasswordPairs参数,还支持varMask Regexes参数,使用自定义的正则表达式匹配需要隐藏的文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //该示例会抛出一个异常:java.lang.IllegalStateException: wrap step must be called with a body pipeline { agent any environment { SECRET1 = "abc-xxx" SECRET2 = "xxxabc-xxx" NOT_SECRET1 = "abcxxx" } stages { stage( "read vault key" ) { steps { wrap(maskPasswords( varMaskRegexes: [[regex: 'abc-.*' ]]) { echo "${SECRET1}" //输出的是密文 echo "${SECRET1}" //输出的是密文 echo "${NOT_SECRET1}" //输出的是明文 } ) } } } } |
4.3、设置全局级别的密文隐藏
- 通过Masked Password插件还可以设置全局级别的密文隐藏。
- Jenkins --> Manage Jenkins --> Configure System
1
1 | # # |
分类:
DevOps-Jenkins
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本