【问题标题】:Pass Jenkins credentials to Maven Surefire plugin将 Jenkins 凭证传递给 Maven Surefire 插件
【发布时间】:2022-01-06 16:27:47
【问题描述】:

背景

我正在开发一个模板化的管道解决方案,这样团队就可以在 Jenkins 中运行的每项工作中始终如一地构建、测试和扫描他们的项目。其中一个项目使用 Maven 进行依赖管理,并且需要传递 Jenkins 凭据才能运行集成测试。

什么有效?

通过命令行参数传递凭据可以正常工作。比如……

withCredentials([
    [
        $class: 'UsernamePasswordMultiBinding', 
        credentialsId: 'TEST', 
        usernameVariable: 'TEST_USERNAME', 
        passwordVariable: 'TEST_PASSWORD'
    ]
]) {
    sh 'mvn clean install -D test_username=$TEST_USERNAME -D test_password=$TEST_PASSWORD'
}

想要的方法和结果是什么?

我强烈希望通过每个插件的配置(即 Maven Surefire 插件)将这些变量传递给底层插件。这种首选方法的理由是利用结构化方法来管理系统属性。我尝试了多种方法,包括通过设置 Surefire 配置的 <argLines> 元素和设置 <systemPropertyValues> 元素来传递参数,但是这两种方法都不起作用。此外,最好通过 YAML 文件引用这些属性以实现外部化配置,但我不反对访问这些信息的其他方法如果无法在配置文件中引用凭据变量。。 p>

pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <!-- Tacking 'env.' to the beginning of each variable name does not make a difference; tests still fail. -->
        <argLines>-D test_username=${TEST_USERNAME} -D test_password=${TEST_PASSWORD}</argLines>
        <systemPropertyVariables>
            <test_username>${TEST_USERNAME}</test_username>
            <test_username>${TEST_PASSWORD}</test_username>
        </systemPropertyVariables>
    </configuration>
</plugin>

bootstrap-test.yaml

datasource:
    jdbc_url: *omitted*
    username: ${test_username}
    password: ${test_password}

不工作是什么意思?

如果我尝试通过在配置部分中指定系统属性来在 Jenkins 环境中运行测试,那么测试会失败。顺便说一句,我将这些凭据传递给 Spring Boot,但 entityManagerFactory (org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder) 无法初始化。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/acme/Config.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: Unable to resolve persistence unit root URL

我担心这个问题可能是由于 Spring Boot 无法访问混淆凭据,或者尝试在 Maven 生命周期中太晚访问配置文件中的系统属性。

我也不完全反对通过命令行传递系统属性,但模板化解决方案需要包含一种有效(安全)的方式来收集不同的凭证类型以传递给 Maven 调用。

更新 1

在导出变量后在本地(顺便说一下,在 Windows 机器上)运行此项目确实有效,但在 Jenkins 中不起作用。在本地工作的方法涉及在 Surefire 插件配置部分设置环境或系统属性变量。我确实使用 env. 对 Jenkins 创建的环境变量进行了前缀引用。

更新 2

使用 Maven antrun 插件,我能够回显 Jenkins 导出的掩码。

【问题讨论】:

  • 您是否尝试将它们作为“秘密”存储在 Jenkins 中?我这样做是为了在我的应用程序中解密加密文件。我认为如果您将它们存储为(例如)“MAVEN_PWD”,您应该能够在运行时检索它们。
  • @hfontanez 是的,测试仍然无法解析外部化变量。您是如何访问您提到的项目中的这些变量的?命令行参数、Surefire 插件配置等?
  • #1 您使用的是脚本化管道还是声明性管道? #2 像 maven 这样的 Java 框架并不关心 jenkins 如何管理它的变量。通常那些使用环境变量来避免硬编码值。有没有适合你的选择,使用环境变量?
  • @JRichardsz 我正在使用声明性管道并开放使用环境变量。
  • @MikeDeitrick 不幸的是我不记得了,我不再受雇于我做这件事的地方。但是,我认为 JRichardsz 很喜欢。

标签: java maven jenkins credentials


【解决方案1】:

我尝试了一个新的詹金斯,它按预期工作。如果插件(java 类)能够读取环境变量并且 jenkins 注入环境变量,那么一切都应该工作。

我认为您的错误是环境变量语法。根据this,您应该使用 ${env.VARIABLE_NAME} 在 pom.xml 中使用 环境变量。所以在你的情况下,你的 pom.xml 应该是这样的:

<test_username>${env.TEST_USERNAME}</test_username>
<test_username>${env.TEST_PASSWORD}</test_username>

然后用

注入所需的变量
withCredentials([
    [
        $class: 'UsernamePasswordMultiBinding', 
        credentialsId: 'TEST', 
        usernameVariable: 'TEST_USERNAME', 
        passwordVariable: 'TEST_PASSWORD'
    ]
]) {
    sh 'mvn clean install'
}

Java 系统属性和环境变量

当您在任何 java 实现中使用 -Dmykey = value 时,您设置的是系统属性,不是环境变量。检查这个:

【讨论】:

  • 感谢您的详细回复。我尝试在 pom.xml 的主要属性部分添加引用环境变量的新属性(即&lt;secret&gt;${env.SECRET}&lt;/secret&gt;),但现在我看到了一个稍微不同的错误。似乎测试配置(bootstrap-test.yaml)将"${secret}"(带或不带双引号)视为文字值,而不执行任何字符串插值。我意识到这与我原来的问题完全不同。我想说你描述的方法会起作用,但我不确定......
  • 你可以尝试不使用 jenkins。使用export TEST_USERNAME=john 在shell 上直接注入env var,然后在你的pom.xml ${env.TEST_USERNAME} 中,直接在shell 上运行你的maven 命令:mvn clean package。如果它有效,jenkins 将有效。如果不能在 shell 中工作,则不能在 jenkins 上工作。
  • 基于您的建议的有趣发现...在导出变量后在本地(顺便说一下,在 Windows 机器上)运行该项目确实有效,但 在詹金斯工作。在本地工作的方法涉及在 Surefire 插件配置部分设置环境或系统属性变量。我确实使用 env. 对 Jenkins 创建的环境变量的引用进行了前缀引用。我将根据这些发现更新我的问题。
  • 添加了一项关于通过 Maven antrun 插件验证 Jenkins 环境变量的更新。
  • 真的很奇怪的发现——我最初用mvn clean install -f ./pom.xml... 打电话给Maven,因为人们有能力调整他们的POM 的位置(但鼓励遵循Maven 约定)。事实证明,将 './pom.xml' 传递给 Maven 时发生了一些非常奇怪的事情,但 'pom.xml' 实际上可以完美地解析环境变量。我不知道为什么会这样,但我会接受你的回答,因为它在逻辑上是有道理的。
【解决方案2】:

这非常奇怪,但是如何指定 POM 位置似乎会有所不同。最初我向 Maven 提供 -f ./pom.xml 并且无法解析环境变量。一时兴起,我提供了f pom.xml(没有'./')和成功解析的环境变量。

不幸的是,我不知道为什么这会有所不同,但如果我设法在以后发现更多细节,我会更新我的答案...

【讨论】:

  • 解释:微软视窗。感谢上帝,真正的服务器是Linux
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 2021-04-25
  • 2019-02-02
  • 2012-05-11
相关资源
最近更新 更多