共享库全局变量中的字符串插值
String interpolation in a shared library's global variable
云蜂 2.289.1.2
我正在根据 Jenkinsfile string interpolation 指南更改代码。
注意:我知道 Groovy 字符串插值需要包含变量的双引号。
共享库中的几个全局变量(在vars/下)有几个sh。
目前(不使用 Jenkins 的字符串插值指令),下面指定的命令会给出警告(在每个命令后显示)。
第一个命令:
此命令无法填充 custom/user-defined 变量,但 似乎 填充了用户名和密码:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}"
.toLowerCase()
// tag images
withCredentials([usernamePassword(
credentialsId: pushCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://$resultingImage:latest docker://$resultingImage:$tagName --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying ${resultingImage}:${tagName}"'
}
}
输出:
[Pipeline] withCredentials
Masking supported pattern matches of $username or $password
[Pipeline] {
[Pipeline] sh
+ set +x skopeo copy docker://:latest docker://: --src-tls-verify=false '--src-creds=****:****' '--dest-creds=****:****' echo 'done copying :'
如果使用双引号,则会显示以下警告,但命令格式正确:
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ set +x
第二个命令:
这会引发错误(似乎 凭证已正确检索),无论我使用“${chartTarballName}”还是 ${chartTarballName}或 $chartTarballName:
sh 'curl -f -u $username:$password -T "${chartTarballName}" $chartPublishRepo/$chartTarballName'
错误:
[Pipeline] sh
+ curl -f -u ****:**** -T '' /
curl: (3) <url> malformed
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
ERROR: script returned exit code 3
如果使用双引号,则会显示以下警告,但命令格式正确:
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ curl -f -u ****:**** -T exp-calculator-0.14.11.tgz https://repository.net/artifactory/stable-local/exp-calculator-0.14.11.tgz
我猜想这些插值规则只适用于声明性管道指令,不适用于共享库中的脚本管道、全局变量(至少是用户定义的变量)和其他 Groovy DSL脚本。
更新 1:
单引号似乎只适用于标准指令管道指令:
pipeline {
environment {
CUSTOM_ENV_VAR = 'This is an environment variable'
}
agent any
stages {
stage('build') {
steps {
withCredentials([string(credentialsId: 'sq_token', variable: 'SECRET')]) {
sh ("echo $SECRET")
sh ('echo $SECRET $CUSTOM_ENV_VAR')
script {
String scriptBlockVariable = 'This is a variable in a script block'
sh ('echo $scriptBlockVariable')
sh ('echo $SECRET $scriptBlockVariable')
}
}
}
}
}
}
输出:
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] withCredentials
Masking supported pattern matches of $SECRET
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [SECRET]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ echo ****
****
[Pipeline] sh
+ echo **** This is an environment variable
**** This is an environment variable
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo
[Pipeline] sh
+ echo ****
****
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
[Pipeline] // stage
试着这样看:当你执行一个使用解释器的作业时,如sh
、bat
和powershell
,有两个单独的上下文保存参数执行。
第一个上下文是实际的 groovy 代码,它包含代码定义的所有参数,它可以是输入参数、全局参数或在代码中使用 def
关键字定义的任何参数。
第二个上下文是参数集,每当您 运行 解释器步骤(sh
、bat
、powershell
时,这些参数将被加载到执行 运行time 环境中),此参数将作为环境参数提供给这些步骤。
第一个上下文groovy运行的string interpolation只能访问代码中定义的变量,而[=78=传递和执行的命令] 步骤只能访问第二个上下文中的参数。在您的情况下,您将两者混合在一起。
现在让我们检查一下不同的关键字及其范围:
用于定义参数的简单 def
语句将使它可用于 第一个上下文 - groovy 代码以及字符串插值。
声明管道中的 parameters
块是一个特殊关键字,它使参数在 两种上下文中都可用 - 它可用于 groovy 代码,但也作为运行 shell 步 environment.It 时间环境的环境变量支持常规参数和凭据。
脚本化管道不能使用 parameters
指令,相反它们有一个不同的关键字用于向执行环境添加参数,称为 withEnv:
withEnv
- Sets one or more environment variables within a block. These are available to any external processes spawned within that scope.
withEnv
仅支持常规参数,因此引入了另一个关键字来支持凭据:withCredentials 可以像 withEnv
步骤那样设置凭据参数。
回到你的问题:
Jenkins确实recommends不对敏感参数使用字符串插值,而是将它们传递给执行环境(context 2)并让shell 步骤将它们用作环境变量,因此您需要用单引号定义字符串,但另一方面,您希望使用代码中定义的参数 (context 1)只能使用需要双引号的字符串插值进行评估。所以你实际上是在尝试同时使用来自两个上下文的参数,这有点棘手。
处理这种混合物有两种选择:
1 - 在 withEnv
关键字旁边使用 withCredentials
,使用 shell 语法参数参考 ($
) 用单引号定义字符串(禁用字符串插值)并让 shell 从环境变量中提取所有参数 。类似于:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password',usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
withEnv(['TAG_NAME=tagName', "IMAGE=${resultingImage}"]) {
sh 'set +x skopeo copy docker://$IMAGE:latest docker://$IMAGE:$TAG_NAME --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying $IMAGE:$TAG_NAME"'
}
}
}
2 - 将命令字符串的创建分成几个部分,每个部分处理正确的上下文 - groovy 将在创建命令时评估参数,仅评估相关参数 将被 shell 命令提取。类似于:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password', usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://' + resultingImage + ':latest docker://' + "${resultingImage}:${tagName}" + '--src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo' + /"done copying ${resultingImage}:${tagName}"/
}
}
这里非常nice article介绍了Jenkins的环境变量和用法
云蜂 2.289.1.2
我正在根据 Jenkinsfile string interpolation 指南更改代码。 注意:我知道 Groovy 字符串插值需要包含变量的双引号。
共享库中的几个全局变量(在vars/下)有几个sh。
目前(不使用 Jenkins 的字符串插值指令),下面指定的命令会给出警告(在每个命令后显示)。
第一个命令: 此命令无法填充 custom/user-defined 变量,但 似乎 填充了用户名和密码:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}"
.toLowerCase()
// tag images
withCredentials([usernamePassword(
credentialsId: pushCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://$resultingImage:latest docker://$resultingImage:$tagName --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying ${resultingImage}:${tagName}"'
}
}
输出:
[Pipeline] withCredentials
Masking supported pattern matches of $username or $password
[Pipeline] {
[Pipeline] sh
+ set +x skopeo copy docker://:latest docker://: --src-tls-verify=false '--src-creds=****:****' '--dest-creds=****:****' echo 'done copying :'
如果使用双引号,则会显示以下警告,但命令格式正确:
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ set +x
第二个命令: 这会引发错误(似乎 凭证已正确检索),无论我使用“${chartTarballName}”还是 ${chartTarballName}或 $chartTarballName:
sh 'curl -f -u $username:$password -T "${chartTarballName}" $chartPublishRepo/$chartTarballName'
错误:
[Pipeline] sh
+ curl -f -u ****:**** -T '' /
curl: (3) <url> malformed
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
ERROR: script returned exit code 3
如果使用双引号,则会显示以下警告,但命令格式正确:
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ curl -f -u ****:**** -T exp-calculator-0.14.11.tgz https://repository.net/artifactory/stable-local/exp-calculator-0.14.11.tgz
我猜想这些插值规则只适用于声明性管道指令,不适用于共享库中的脚本管道、全局变量(至少是用户定义的变量)和其他 Groovy DSL脚本。
更新 1:
单引号似乎只适用于标准指令管道指令:
pipeline {
environment {
CUSTOM_ENV_VAR = 'This is an environment variable'
}
agent any
stages {
stage('build') {
steps {
withCredentials([string(credentialsId: 'sq_token', variable: 'SECRET')]) {
sh ("echo $SECRET")
sh ('echo $SECRET $CUSTOM_ENV_VAR')
script {
String scriptBlockVariable = 'This is a variable in a script block'
sh ('echo $scriptBlockVariable')
sh ('echo $SECRET $scriptBlockVariable')
}
}
}
}
}
}
输出:
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] withCredentials
Masking supported pattern matches of $SECRET
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [SECRET]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ echo ****
****
[Pipeline] sh
+ echo **** This is an environment variable
**** This is an environment variable
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo
[Pipeline] sh
+ echo ****
****
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
[Pipeline] // stage
试着这样看:当你执行一个使用解释器的作业时,如sh
、bat
和powershell
,有两个单独的上下文保存参数执行。
第一个上下文是实际的 groovy 代码,它包含代码定义的所有参数,它可以是输入参数、全局参数或在代码中使用 def
关键字定义的任何参数。
第二个上下文是参数集,每当您 运行 解释器步骤(sh
、bat
、powershell
时,这些参数将被加载到执行 运行time 环境中),此参数将作为环境参数提供给这些步骤。
第一个上下文groovy运行的string interpolation只能访问代码中定义的变量,而[=78=传递和执行的命令] 步骤只能访问第二个上下文中的参数。在您的情况下,您将两者混合在一起。
现在让我们检查一下不同的关键字及其范围:
用于定义参数的简单 def
语句将使它可用于 第一个上下文 - groovy 代码以及字符串插值。
声明管道中的 parameters
块是一个特殊关键字,它使参数在 两种上下文中都可用 - 它可用于 groovy 代码,但也作为运行 shell 步 environment.It 时间环境的环境变量支持常规参数和凭据。
脚本化管道不能使用 parameters
指令,相反它们有一个不同的关键字用于向执行环境添加参数,称为 withEnv:
withEnv
- Sets one or more environment variables within a block. These are available to any external processes spawned within that scope.
withEnv
仅支持常规参数,因此引入了另一个关键字来支持凭据:withCredentials 可以像 withEnv
步骤那样设置凭据参数。
回到你的问题:
Jenkins确实recommends不对敏感参数使用字符串插值,而是将它们传递给执行环境(context 2)并让shell 步骤将它们用作环境变量,因此您需要用单引号定义字符串,但另一方面,您希望使用代码中定义的参数 (context 1)只能使用需要双引号的字符串插值进行评估。所以你实际上是在尝试同时使用来自两个上下文的参数,这有点棘手。
处理这种混合物有两种选择:
1 - 在 withEnv
关键字旁边使用 withCredentials
,使用 shell 语法参数参考 ($
) 用单引号定义字符串(禁用字符串插值)并让 shell 从环境变量中提取所有参数 。类似于:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password',usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
withEnv(['TAG_NAME=tagName', "IMAGE=${resultingImage}"]) {
sh 'set +x skopeo copy docker://$IMAGE:latest docker://$IMAGE:$TAG_NAME --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying $IMAGE:$TAG_NAME"'
}
}
}
2 - 将命令字符串的创建分成几个部分,每个部分处理正确的上下文 - groovy 将在创建命令时评估参数,仅评估相关参数 将被 shell 命令提取。类似于:
String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password', usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://' + resultingImage + ':latest docker://' + "${resultingImage}:${tagName}" + '--src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo' + /"done copying ${resultingImage}:${tagName}"/
}
}
这里非常nice article介绍了Jenkins的环境变量和用法