当前位置: 首页 > 知识库问答 >
问题:

防止Jenkins作业参数中环境变量的扩展

殳俊晤
2023-03-14

我正在做一个Jenkins的工作,它接受来自用户的一些参数。我遇到了一个不希望的行为:在我的脚本有机会读取环境变量之前,Jenkins似乎在参数环境变量中扩展了环境变量引用。

如果用户输入 foo-$BUILD_NUMBER 作为参数,我的脚本实际看到的是类似于 foo-123 的内容;环境变量已展开。如果输入的值包含 $$,我的脚本只能看到一个 $。但是,如果它包含环境中不存在的$variable,则该值将保持不变(不会引发任何类型的错误)。

这很不方便,因为它甚至出现在密码字段中,我通常使用一个密码生成器,它可以包含$字符。我不希望我的密码可能被默默地篡改。

我最初的测试用例如下,使用 Jenkins Job Builder Groovy DSL。

new BaseJobBuilder(
    jobName: 'example',
    jobBuildName: 'example-${BUILD_NUMBER}',
).build(this).with {
    parameters {
        nonStoredPasswordParam('SERVICE_PASSWORD')
    }
    steps {
        shell('echo "$SERVICE_PASSWORD";')
    }
}

然而,对于一个更简化的测试用例,我从< code > Jenkins/Jenkins:lts Docker映像创建了一个新的Jenkins安装,在没有任何插件的情况下对其进行了配置(甚至是默认的),并使用web UI创建了一个等效的作业。

当我使用参数 SERVICE_PASSWORD 的值 hello $BUILD_NUMBER $HOME world 运行这些作业中的任何一个时,输出会扩展变量,而不是我想要的文本值。

Started by user jeremy
Building in workspace /var/jenkins_home/workspace/jeremy
[jeremy] $ /bin/sh -xe /tmp/jenkins2451955822062381529.sh
+ echo hello 3 /var/jenkins_home world
hello 3 /var/jenkins_home world
Finished: SUCCESS

有没有办法在 Jenkins 受到变量扩展/插值之前访问它们的原始参数值,或者以其他方式禁用或规避此行为?

我如何接受可能包含< code>$美元字符的原始文本参数,而不冒被破坏的风险?

  • JENKINS-10779不存在的参数不为空,而是替换为参数名称
  • JENKINS-16143Jenkins在参数化构建字段中转义2美元符号
  • JENKINS-26916构建参数中应该有一个打开/关闭变量替换的选项
  • Jenkins文本参数-特殊字符乱码(不需要的变量替换)

共有1个答案

尉迟彬
2023-03-14

作为一种解决方法,我们可以添加一个初始构建步骤,该步骤直接读取所有参数并将其编码在Base64中,然后将编码值导出为新的环境变量。Base64编码的值不能包含任何美元字符$,因此它们可以被以后的构建步骤安全地读取,这些步骤可以对它们进行解码以获得原始值,而无需任何扩展。

我们使用Groovy插件中的“System Groovy脚本”构建步骤来实现这一点,该步骤运行一个自定义Groovy脚本,可以直接访问构建状态(感谢daspilker的建议)。如果您使用的是DSL,则可以使用systemGroovyCommand(“”“...”“”)调用添加此内容。

import hudson.EnvVars;
import hudson.model.Executor;
import hudson.model.Environment;

def build = Executor.currentExecutor().currentExecutable;

def newVariables = [:];
build.getBuildVariables().each { name, value ->
  def encodedName = name + "_B64";
  def encodedValue = value.bytes.encodeBase64().toString();
  newVariables.put(encodedName, encodedValue);
}

build.getEnvironments().add(Environment.create(new EnvVars(newVariables)))

您的Jenkins管理员可能需要在第一次加载此脚本时从进程内脚本批准页面批准它。因为它已经对所有参数进行了编码,因此您不需要修改它,并且可以在其他作业中重复使用它而无需重新批准。

随后的“执行Shell”步骤现在将能够解码原始值。

set -eu +vx;

echo "directly from environment: $SERVICE_PASSWORD";

SERVICE_PASSWORD="$(echo "$SERVICE_PASSWORD_B64" | base64 --decode)";
echo "via base-64 encoded value: $SERVICE_PASSWORD";

我们可以使用我们的原始测试值< code > hello $ BUILD _ NUMBER $ HOME world 来确认它是否工作:

directly from environment: hello 12 /var/jenkins_home world
via base-64 encoded value: hello $BUILD_NUMBER $HOME world

从环境变量中读取参数时,无法禁用变量扩展。这种行为与参数无关,而是与Jenkins处理环境变量的方式有关。在<code>hudson.model.AbstractBuild之后。getEnvironment(…)方法聚合构建的所有环境变量,它应用hudson.EnvVars。resolve(…)函数对所有环境变量的内容执行互变量扩展。根据确切的构建配置,它还可以使用hudson.EnvVars。overrideExpandingAll(…),这需要对变量进行拓扑排序,以确保所有非循环引用都以正确的顺序展开。实际的字符串操作由hudson.util执行。replaceMacro(…),其中有一条注释,解释了对不存在的变量的异常处理(非替换):

与 shell 不同,未定义的变量保持原样(此行为与 Ant 相同)。

这些扩展是无条件执行的,因此如果不修改或替换Jenkins中的几个类,就无法禁用它。

 类似资料:
  • 问题内容: 我有一个项目,需要根据用户选择的选择参数设置环境变量。每个项目都有一个主题项目依赖项。我想让用户选择项目,然后从属性文件中加载主题名称。就像是 如果用户从choice参数中选择,我想自动设置为。最好的方法是什么? 每当添加新项目时,我都不想修改Jenkins作业配置。相反,我想将映射保存在文件中,以便可以在版本控制中使用它。 问题答案: 啊哈,我找到了一个简单的解决方案!使用EnvIn

  • 问题内容: Jenkins(管理jenkins->系统信息)下的环境变量从何而来? 我检查了/etc/init.d/tomcat5,/ usr / bin / dtomcat5,/ usr / bin / tomcat5,/ etc / sysconfig / tomcat5和/ etc / profile,但在那里没有看到任何此类变量,特别是与Oracle相关的变量(Base,Home,Ld_l

  • 我正在尝试根据传递到作业中的参数在Jenkins管道作业中设置环境变量;这样,我可以在需要它的管道的每个阶段使用环境变量。我尝试在环境块中使用Switch语句: 然而,这并不起作用,该作业试图将等号之前的所有行评估为KEY名称: 我该如何让它工作?

  • 问题内容: 我正在从已设置用户权限的用户那里运行Jenkins ,当我进入Jenkins Web界面时,在“ 系统属性” 窗口()中看到了一个不同的。 我已经使用Jenkins网站上的本地rpm在Centos上安装了Jenkins。我正在使用安装随附的启动脚本 谁能告诉我为什么会这样? 问题答案: 迈克尔 两件事情: 当詹金斯连接到计算机时,它将连接到外壳,而不是外壳(至少这是我注意到的-我可能错

  • 问题内容: 是否有任何环境变量可用于获取Jenkins管道标题? 我知道我们可以使用它来获得自由职业的头衔,但是有什么可以用来获取管道名称的东西吗? 问题答案: 您可以使用相同的名称(例如或)从groovy访问相同的环境变量。 从文档中: 可以从Groovy代码中以env.VARNAME或仅以VARNAME的形式访问环境变量。您也可以写入这些属性(仅使用env。前缀): 这些定义也将在构建期间或构

  • 我正在构建Jenkins的Docker映像,并已将ENV变量传递给< code>jenkins.sh初始化文件: Dockerfile文件 詹金斯. sh 当我运行图像时,这些值可以完美地打印出来,但是我想在Jenkins初始化期间在Groovy脚本中使用它们。 以下在启动期间引发错误: 错误 警告:无法运行脚本文件:/var/jenkins_home/init.groovy.d/init_ecs