Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-45335

mavenOpts attribute doesn't resolve credentials variables

      This doesn't work:

                withCredentials([string(credentialsId: 'mvnrepo-keystore-pass', variable: 'JENKINSPASS')]) {
                    withMaven( 
                      mavenOpts: '-Djavax.net.ssl.keyStore=effaced.p12    -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStorePassword=${JENKINSPASS}',
                      mavenSettingsConfig: 'my-maven-settings') {
                      sh 'mvn help:effective-settings -U'
                  }
                }  

      This does work:

                withCredentials([string(credentialsId: 'mvnrepo-keystore-pass', variable: 'JENKINSPASS')]) {
                    withMaven( 
                      mavenSettingsConfig: 'my-maven-settings') {
                      sh 'MAVEN_OPTS="-Djavax.net.ssl.keyStore=effaced.p12  -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStorePassword=${JENKINSPASS}" mvn help:effective-settings -U'
                  }
                }  

          [JENKINS-45335] mavenOpts attribute doesn't resolve credentials variables

          cleclerc I'm using double quotes in my example already, so this isn't it.

           

          Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says:

          Maven JVM Opts (mavenOpts): Specify JVM specific options needed when launching Maven as an external process, these are not maven specific options. See: Java Options
          Shell-like environment variable expansions work in this field, by using the ${VARIABLE} syntax.

          https://wiki.jenkins.io/display/JENKINS/Pipeline+Maven+Plugin#PipelineMavenPlugin-Usage

          Jakub Bochenski added a comment - cleclerc I'm using double quotes in my example already, so this isn't it.   Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says: Maven JVM Opts ( mavenOpts ): Specify JVM specific options needed when launching Maven as an external process, these are not maven specific options. See: Java Options Shell-like environment variable expansions work in this field, by using the ${VARIABLE } syntax. https://wiki.jenkins.io/display/JENKINS/Pipeline+Maven+Plugin#PipelineMavenPlugin-Usage

          jbochenski

          Could you please try the following syntax that is slightly different from what you have used:

          withCredentials(
          	[string(credentialsId: 'mvnrepo-keystore-pass', variable: 'JENKINSPASS')]) {
          
              // use ${env.JENKINSPASS} instead of ${JENKINSPASS}
              // use "double quotes" instead of 'single quotes' for the "mavenOpts" attribute
              withMaven( 
          		mavenOpts: "... -Djavax.net.ssl.keyStorePassword=${env.JENKINSPASS}",
          		mavenSettingsConfig: 'my-maven-settings') {
          
          	    sh 'mvn help:effective-settings -U'
          	}
          }  
          

          > Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says:

          correct, we have to fix this doc

          Cyrille Le Clerc added a comment - jbochenski Could you please try the following syntax that is slightly different from what you have used: withCredentials( [string(credentialsId: 'mvnrepo-keystore-pass' , variable: 'JENKINSPASS' )]) { // use ${env.JENKINSPASS} instead of ${JENKINSPASS} // use " double quotes" instead of 'single quotes' for the "mavenOpts" attribute withMaven( mavenOpts: "... -Djavax.net.ssl.keyStorePassword=${env.JENKINSPASS}" , mavenSettingsConfig: 'my-maven-settings' ) { sh 'mvn help:effective-settings -U' } } > Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says: correct, we have to fix this doc

          Jakub Bochenski added a comment - - edited

          cleclerc
          > Could you please try the following syntax that is slightly different from what you have used:

          I already tried double quotes in https://issues.jenkins-ci.org/browse/JENKINS-45335?focusedCommentId=315498&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-315498 and it still doesn't work.

          It's a wild shot but maybe it's related to JENKINS-46814 or JENKINS-26583 – we do have MAVEN_OPTS set in Global Properties | Environment Variables

          > > Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says:

          > correct, we have to fix this doc
          I'm not sure about that. The old MAVEN_OPTS from Maven project/Invoke Top-Level Maven steps used to accept $SHELL_VARIABLES. Especially during migration it's useful for the new mavenOpts to support the same format

          Jakub Bochenski added a comment - - edited cleclerc > Could you please try the following syntax that is slightly different from what you have used: I already tried double quotes in https://issues.jenkins-ci.org/browse/JENKINS-45335?focusedCommentId=315498&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-315498 and it still doesn't work. It's a wild shot but maybe it's related to JENKINS-46814 or JENKINS-26583 – we do have MAVEN_OPTS set in Global Properties | Environment Variables > > Also: double quotes is just groovy strings interpolating variables. This isn't what the docs says: > correct, we have to fix this doc I'm not sure about that. The old MAVEN_OPTS from Maven project/Invoke Top-Level Maven steps used to accept $SHELL_VARIABLES. Especially during migration it's useful for the new mavenOpts to support the same format

          Using
          mavenOpts: "-Djarsigner.storepass=${env.KEYSTORE_PASSWORD}"
          (with double quotes) now results in a warning
          Warning: A secret was passed to "withMaven" using Groovy String interpolation, which is insecure.
          Affected argument(s) used the following variable(s): [KEYSTORE_PASSWORD]
          See https://jenkins.io/redirect/groovy-string-interpolation for details.
          So what's the recommended way to pass credentials to Maven now?

          Thorsten Meinl added a comment - Using mavenOpts: "-Djarsigner.storepass=${env.KEYSTORE_PASSWORD}" (with double quotes) now results in a warning Warning: A secret was passed to "withMaven" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [KEYSTORE_PASSWORD] See https://jenkins.io/redirect/groovy-string-interpolation for details. So what's the recommended way to pass credentials to Maven now?

          I am not yet sure sithmein

          I have to study the question with some experts in this domain.

          My understanding is that the plugin should allow to do something like without groovy interpolation but it doesn't (thus the solution proposed by cleclerc)

           

          withCredentials(
          	[string(credentialsId: 'mvnrepo-keystore-pass', variable: 'JENKINSPASS')]) {
          
              withMaven( 
          		mavenOpts: '... -Djavax.net.ssl.keyStorePassword=${JENKINSPASS}',
          		mavenSettingsConfig: 'my-maven-settings') {
          
          	    sh 'mvn help:effective-settings -U'
          	}
          }  
          

          danielbeck wfollonier or jglick do you have some links / samples to implement this correctly ?

           

          For now we just do this which is expending the environment variables but could allow to use directly some credentials

          Arnaud Héritier added a comment - I am not yet sure sithmein I have to study the question with some experts in this domain. My understanding is that the plugin should allow to do something like without groovy interpolation but it doesn't (thus the solution proposed by cleclerc )   withCredentials( [string(credentialsId: 'mvnrepo-keystore-pass' , variable: 'JENKINSPASS' )]) { withMaven( mavenOpts: '... -Djavax.net.ssl.keyStorePassword=${JENKINSPASS}' , mavenSettingsConfig: 'my-maven-settings' ) { sh 'mvn help:effective-settings -U' } } danielbeck wfollonier  or jglick  do you have some links / samples to implement this correctly ?   For now we just do this which is expending the environment variables but could allow to use directly some credentials

          Pinging also jvz who work recently on credentials-plugin.

          I don't know if there is a clean way to do so already done in the ecosystem. I just have concerns about the potential impact of such approach in terms of secret masking.

          Wadeck Follonier added a comment - Pinging also jvz who work recently on credentials-plugin. I don't know if there is a clean way to do so already done in the ecosystem. I just have concerns about the potential impact of such approach in terms of secret masking.

          Aren't the mavenOpts injected as environment variable MAVEN_OPTS into the sh step? At least I don't see the contents anywhere in the log. If this is true then the warning is a false positive and the check needs to be fixed.

          Thorsten Meinl added a comment - Aren't the mavenOpts injected as environment variable MAVEN_OPTS into the sh step? At least I don't see the contents anywhere in the log. If this is true then the warning is a false positive and the check needs to be fixed.

          sithmein I am just telling that about the potential change here, not the current implementation

          The warning seems accurate enough. If you are inject secrets using double quotes, you can be in troubles due to interpretation by Groovy and then, by shell / maven / other system. Depending on the secret content (like single quote, double quotes, symbols, etc.), the command will not be exactly what you expected.

          You can try yourself if your secret contain something like "s3cr3t -DotherArg=test", using the double quotes approach, you will get the new argument added to your command line. (not tested)

          Wadeck Follonier added a comment - sithmein I am just telling that about the potential change here, not the current implementation The warning seems accurate enough. If you are inject secrets using double quotes, you can be in troubles due to interpretation by Groovy and then, by shell / maven / other system. Depending on the secret content (like single quote, double quotes, symbols, etc.), the command will not be exactly what you expected. You can try yourself if your secret contain something like "s3cr3t -DotherArg=test", using the double quotes approach, you will get the new argument added to your command line. (not tested)

          That's why we quote the argument values in our case (-Dpassword=\"${PASSWORD}\"). But I get your point and even the quotes are probably not 100% safe.

          Thorsten Meinl added a comment - That's why we quote the argument values in our case ( -Dpassword=\"${PASSWORD}\" ). But I get your point and even the quotes are probably not 100% safe.

          Matt Sicker added a comment - - edited

          The withCredentials step binds the credential values to the environment variable provided. In the double quote case, this means it's being filled in by Groovy/Pipelines as pipeline variable (equivalent to doing 'foo' + bar + 'baz' in Groovy: "foo${bar}baz". If the withMaven step were to support some sort of pseudo-templates in its parameters, that would allow for single quote usage, but that API is using a single variable for this, so you'd need an extra level of shell escaping to ensure that the mavenOpts string is split into its args without splitting a password with a space or other special character in it. To be honest, I usually avoid using the withMaven step and just use a own custom one all the time similar to the one I use here: https://github.com/apache/logging-pipelines/blob/master/vars/mvn.groovy (with some hard-coded tool installations, but you can use the tool DSL instead). Then I can at least bind the maven arguments directly in the sh or bat step to quote everything properly.

          Matt Sicker added a comment - - edited The withCredentials step binds the credential values to the environment variable provided. In the double quote case, this means it's being filled in by Groovy/Pipelines as pipeline variable (equivalent to doing 'foo' + bar + 'baz' in Groovy: "foo${bar}baz" . If the withMaven step were to support some sort of pseudo-templates in its parameters, that would allow for single quote usage, but that API is using a single variable for this, so you'd need an extra level of shell escaping to ensure that the mavenOpts string is split into its args without splitting a password with a space or other special character in it. To be honest, I usually avoid using the withMaven step and just use a own custom one all the time similar to the one I use here: https://github.com/apache/logging-pipelines/blob/master/vars/mvn.groovy (with some hard-coded tool installations, but you can use the tool DSL instead). Then I can at least bind the maven arguments directly in the sh or bat step to quote everything properly.

            Unassigned Unassigned
            jbochenski Jakub Bochenski
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: