Groovy Help : Inject passwords to the build as environment variables

5,680 views
Skip to first unread message

Srini

unread,
Mar 10, 2015, 3:29:32 PM3/10/15
to job-dsl...@googlegroups.com
Hi , 

Am looking for help in converting below xml block into groovy configure block. 

<buildWrappers>
<EnvInjectPasswordWrapper>
<injectGlobalPasswords>false</injectGlobalPasswords>
<passwordEntries>
<EnvInjectPasswordEntry>
<name>DEV_PWD</name>
<value>test123</value>
</EnvInjectPasswordEntry>
<EnvInjectPasswordEntry>
<name>TEST_PWD</name>
<value>test123</value>
</EnvInjectPasswordEntry>
</passwordEntries>
</EnvInjectPasswordWrapper>
</buildWrappers>

I have tried using below block but TEST_PWD is overriding the DEV_PWD . 

configure { 
def gblpass = it / 'buildWrappers'  / 'EnvInjectPasswordWrapper'  / 'passwordEntries' / 'EnvInjectPasswordEntry'
injectGlobalPasswords(true) 
(gblpass / 'name').setValue ("DEV_PWD")
(gblpass / 'password').setValue ("test123")
                        (gblpass / 'name').setValue ("TEST_PWD")
(gblpass / 'password').setValue ("test123")

Jeremy Marshall

unread,
Mar 10, 2015, 4:31:35 PM3/10/15
to job-dsl...@googlegroups.com

Hi 

try this

You were close but the shift (<<) operator adds an array item - in this case to the password entries node

job {
  name 'test99'
  configure { 
    def gblpass = it / 'buildWrappers'  / 'EnvInjectPasswordWrapper'  / 'passwordEntries' / 
    injectGlobalPasswords(true) 
    EnvInjectPasswordEntry
    gblpass << 
      'EnvInjectPasswordEntry' {
      name("DEV_PWD")
      'password' "test123"
      }
    gblpass <<
      'EnvInjectPasswordEntry' {
      name("TEST_PWD")
        'password' "test123"
    }
  }
}

which gives this on my Jenkins

<project>
<actions/>
<description/>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class="vector"/>
<concurrentBuild>false</concurrentBuild>
<builders/>
<publishers/>
<buildWrappers>
<EnvInjectPasswordWrapper>
<passwordEntries>
<injectGlobalPasswords>
true
<EnvInjectPasswordEntry>
<name>DEV_PWD</name>
<password>test123</password>
</EnvInjectPasswordEntry>
<EnvInjectPasswordEntry>
<name>TEST_PWD</name>
<password>test123</password>
</EnvInjectPasswordEntry>
</injectGlobalPasswords>
</passwordEntries>
</EnvInjectPasswordWrapper>
</buildWrappers>
</project>

Jeremy Marshall

unread,
Mar 10, 2015, 4:35:54 PM3/10/15
to job-dsl...@googlegroups.com

corrected to remove unused item
...

job
{

  name
'test99'
  configure
{
   
def gblpass = it / 'buildWrappers'  / 'EnvInjectPasswordWrapper'  / 'passwordEntries' /
    injectGlobalPasswords
(true)



    gblpass
<<
     
'EnvInjectPasswordEntry' {

Daniel Spilker

unread,
Mar 10, 2015, 5:38:21 PM3/10/15
to job-dsl...@googlegroups.com
Hi!

You can't set passwords in the DSL with the EnvInject plugin. The passwords are stored encrypted in the XML, e.g. on my Jenkins a password named 'foo' with value 'bar' is stored like this:

<EnvInjectPasswordWrapper plugin="envi...@1.91">
  <injectGlobalPasswords>false</injectGlobalPasswords>
  <maskPasswordParameters>true</maskPasswordParameters>
  <passwordEntries>
    <EnvInjectPasswordEntry>
      <name>foo</name>
      <value>uVEbp1tWSh/MLmYrWqsqMvELvnUr3d+TjkjkCQvFm+A=</value>
    </EnvInjectPasswordEntry>
  </passwordEntries>
</EnvInjectPasswordWrapper>


And apart from that, storing passwords in clear text in the DSL is a security vulnerability.

You can store the password in the global Jenkins configuration and then use the following DSL to inject those passwords as environment variables:

job('test') {
  wrappers {
    injectPasswords()
  }
}

But that will inject all global passwords into the job. You can also use the Credentials plugin with the Credentials Binding plugin to inject only selected passwords into the build:

job('example') {
  wrappers {
    credentialsBinding {
      usernamePassword('PASSWORD', 'keystore password')
    }
  }
}

Daniel


--
You received this message because you are subscribed to the Google Groups "job-dsl-plugin" group.
To unsubscribe from this group and stop receiving emails from it, send an email to job-dsl-plugi...@googlegroups.com.
To post to this group, send email to job-dsl...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/job-dsl-plugin/bae2b786-a507-4176-b78b-a03e98c39e3e%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jeremy Marshall

unread,
Mar 10, 2015, 9:09:23 PM3/10/15
to job-dsl...@googlegroups.com
I thought there would be a better way but it wasn't an area I was familiar with but thought I could give a pointer to how to do it

I suppose my way would work if you put the encrypted password into the script and that is freely available from the config.xml anyway


Bennette John

unread,
Dec 17, 2015, 4:54:45 PM12/17/15
to job-dsl-plugin
Thanks to Jeremy Marshall for helping me with this. I extended his code to get the encrypted password and add that in the configure block. Test it yourself with the below seed job :


import jenkins.*
import hudson.*
import jenkins.model.*
import jenkins.model.Jenkins
import hudson.model.*
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
   com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
   Jenkins.instance,
   null,
   null
);
for (c in creds) {
 if (c.username == "create a username with via http://yourjenkins/credential-store/domain/_/newCredentials and enter it here") {
   credentialID = c.id 
 } 
}
job ('example job') {


 configure { 
   def gblpass = it / 'buildWrappers'  / 'EnvInjectPasswordWrapper'  / 'passwordEntries' / 
     
   EnvInjectPasswordEntry
   gblpass << 
      {
         name("user_name")
         value(credentialID)
     }
 }
}

Pammi Kar

unread,
Jan 18, 2016, 5:58:28 PM1/18/16
to job-dsl-plugin
Looking help to convert below xml:
<EnvInjectPasswordWrapper plugin="envi...@1.91.2">
<injectGlobalPasswords>false</injectGlobalPasswords>
<maskPasswordParameters>true</maskPasswordParameters>
<passwordEntries>
<EnvInjectPasswordEntry>
<name>DEV_PWD</name>
<value>Yl/TxWsnzphnI033s53Hb8yEl+2EFdnTedeE8g4zHwg=</value>
</EnvInjectPasswordEntry>
<EnvInjectPasswordEntry>
<name>TEST_PWD</name>
<value>Yl/TxWsnzphnI033s53Hb8yEl+2EFdnTedeE8g4zHwg=</value>
</EnvInjectPasswordEntry>
</passwordEntries>
</EnvInjectPasswordWrapper>

Am working on gradle jenkin DSL plugin and my code is as below: ( In eed to mask password too)

dsl {
configure { project ->
        
def gblpass = project / 'buildWrappers' /'EnvInjectPasswordWrapper'/ 'passwordEntries' / 
                                
  injectGlobalPasswords (true)
  maskPasswordParameters (true)
      gblpass << 
       'EnvInjectPasswordEntry' {
        name("DEV_PWD")
        'password' "test12"                                  
     }
     gblpass <<
      'EnvInjectPasswordEntry' {
       name("TEST_PWD")
       'password' "test1234"
     }
     
  }  
}

Bennette John

unread,
Jan 28, 2016, 1:47:16 PM1/28/16
to job-dsl-plugin
You can use the below configure block.

configure { 
       
def gblpass = it / 'buildWrappers' /
 
'EnvInjectPasswordWrapper' <<
  {
         injectGlobalPasswords ('false')
         maskPasswordParameters ('true')
  
         passwordEntries() <<
                 {
                   'EnvInjectPasswordEntry'
                           {
                             name('DEV_PWD')
                                value('<NOT RECOMMENDED TO STORE PASSWORD IN PLAIN TEXT, ESPECIALLY IF YOU CHECK IN YOUR DSL INTO GITHUB. LOOK AT MY POST ON 12/17/15 IN THE SAME THREAD WHICH TELLS HOW TO STORE PASSWORD IN JENKINS SERVER AND CALL IT WITHIN YOUR DSL')
                            }
                 }
   }
}

p

unread,
Feb 4, 2016, 8:07:44 PM2/4/16
to job-dsl-plugin
First, thank you for this. This is very helpful. However, how do I do multiple password entries? What if I have another password called PROD_PWD instead of only DEV_PWD? How do I include it? Thank you again.

Bennette John

unread,
Feb 23, 2016, 2:19:00 PM2/23/16
to job-dsl-plugin
Sorry for the delayed response(I haven't subscribed to receive notifications). 

One thing I would like to try is to have the ability to provide the password during the build(build with parameters). That way, the password and environment(PROD/DEV) are stored as an environment variable, and can be passed on to the DSL groovy script(either embedded into the code, or as arguments).

P.S: This is just an idea in my head, and I haven't really tried this.

Bennette John

unread,
Feb 25, 2016, 7:23:16 PM2/25/16
to job-dsl-plugin
For multiple password entries, you just have to add another block :

configure { 
       
def gblpass = it / 'buildWrappers' /
 
'EnvInjectPasswordWrapper' <<
  {
         injectGlobalPasswords ('false')
         maskPasswordParameters ('true')
  
         passwordEntries() <<
                 {
                   'EnvInjectPasswordEntry'
                           {
                             name('DEV_PWD')
                                value('xxxxxx')
                            }
   
                   'EnvInjectPasswordEntry'
                           {
                             name('DEV2_PWD')
                                value('xxxxxx')
                            }
   
                 }
   }
}



On Thursday, February 4, 2016 at 5:07:44 PM UTC-8, p wrote:

Jonathan Zhang

unread,
Jun 4, 2017, 9:59:38 PM6/4/17
to job-dsl-plugin
According to https://issues.jenkins-ci.org/browse/JENKINS-24805,
 Credential Binding Plugin would have a problem to output explicit password into cosole, now this is fixed in Nov. 2016, with version 1.10.
Current jenkins support doc also recommending credential binding :  https://support.cloudbees.com/hc/en-us/articles/203802500-Injecting-Secrets-into-Jenkins-Build-Jobs

For way to use injected variable referred https://groups.google.com/forum/#!searchin/job-dsl-plugin/configure$20secrets|sort:relevance/job-dsl-plugin/c4OizVIq-Pc/Q8kHdkteJAAJ

Now I am doing something like below to read a credential with id "myCredentialId", and command like echo/curl even cat out xml directly would have both userId and password perfectly masked in console
 

job('example') {
  wrappers {
    credentialsBinding {
      usernamePassword('USER','MYPASSWORD', 'myCredentialId')
    }
  }
  shell {
    echo 'my password is : ' \$MYPASSWORD
    curl \$USER:\$MYPASSWORD 'my url'
  }

  def config = new HashMap()
  def bindings = getBinding()
  config.putAll(bindings.getVariables())
  def passwordVarInGroovy = config['MYPASSWORD']

}


在 2015年3月11日星期三 UTC+8上午5:38:21,Daniel Spilker写道:
Reply all
Reply to author
Forward
0 new messages