现象
jenkins pipeline中使用withCredentials
来隐藏账密等敏感信息,结果用sh
方法执行命令时又把用户和密码给打印出来了, 简直了😱
原因
官方文档给出的解释1
Groovy string interpolation can leak sensitive environment variables (i.e. credentials, see: Handling credentials). This is because the sensitive environment variable will be interpolated during Groovy evaluation, and the environment variable’s value could be made available earlier than intended, resulting in sensitive data leaking in various contexts.
Should Groovy perform the interpolation, the sensitive value will be injected directly into the arguments of thesh
step, which among other issues, means that the literal value will be visible as an argument to thesh
process on the agent in OS process listings. Usingsingle-quotes
instead ofdouble-quotes
when referencing these sensitive environment variables prevents this type of leaking.
大致意思就是 Groovy字符串插入可能会泄漏含有敏感信息的环境变量, 比如说凭据中的用户密码等信息, 这是因为环境变量将在Groovy求值期间内插入, 并且环境变量的值可能比预期更早可用, 从而导致敏感信息泄露.
当Groovy进行字符串插入操作时, 环境变量的值会直接插入sh
的参数中, 在操作系统的进程列表中含有敏感信息的环境变量值将作为sh
进程参数明文可见. 预防措施就是在使用这些环境变量时应该使用单引号而不是双引号
文档还给了个错误用法和正确用法的例子
- 错误用法:
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
environment {
EXAMPLE_CREDS = credentials('example-credentials-id')
}
stages {
stage('Example') {
steps {
/* WRONG! */
sh("curl -u ${EXAMPLE_CREDS_USR}:${EXAMPLE_CREDS_PSW} https://example.com/")
}
}
}
}
- 正确用法 :
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
environment {
EXAMPLE_CREDS = credentials('example-credentials-id')
}
stages {
stage('Example') {
steps {
/* CORRECT */
sh('curl -u $EXAMPLE_CREDS_USR:$EXAMPLE_CREDS_PSW https://example.com/')
}
}
}
}
其他方法
通过set +x
可以关闭日志输出避免敏感信息泄露,注意使用的是单引号
2
node {
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh '''
set +x
curl -u "$USERPASS" https://private.server/ > output
'''
}
}
set -x
与 set +x
命令的作用实际是用于输出详细日志,是Shell脚本中使用echo命令输出的替代方案。更适用于输出大量日志的场景使用
set -x
是开启,set +x
是关闭,set -o
是查看 (xtrace
,追踪一段代码的显示情况)
使用双引号
时可能会泄露敏感信息, 下面给一个错误的例子
错误用法:
node {
withCredentials([string(credentialsId: 'mytoken', variable: 'TOKEN')]) {
sh /* WRONG! */ """
set +x
curl -H 'Token: $TOKEN' https://some.api/
"""
}
}