Marcello DeSales
Marcello DeSales

Reputation: 22359

How to reuse Jenkins credentials without masking the PASSWORD in withCredentials.usernamePassword?

Background

All the implementation we have is under the src directory where I reuse the reference in pipelines:

def static myFunction(steps, context) {
  steps.withCredentials([steps.usernamePassword(
      credentialsId: 'credentialsId',
      usernameVariable: 'GITHUB_USERNAME',
      passwordVariable: 'GITHUB_PASSWORD')]) {

     // use of steps.env.GITHUB_PASSWORD
  }
}

As described in https://wiki.jenkins.io/display/JENKINS/Credentials+Binding+Plugin, the problem might be related to how the Credentials binding is masked when used more than once. That is, once we use ${env.PASSWORD} once, it will mask all the uses of the same value.

Detail

I'm using curl to and I need to generate the URL

def teamMembersApi = sh(curl -H 'Authorization: token ${env.PASSWORD}' ${githubRepoApi}")

The response of this call is another API URL, which I created another URL with the "teamMembersApi". So, making the second call...

def teamMembers = sh("curl -H 'Authorization: token ${env.PASSWORD}' ${teamMembersApi}")

At this point, the value of ${env.PASSWORD} is masked and, as a consequence, the second call fails because of invalid credentials

Questions

As I understand, this is a result of the "masking" of values when accessed via any method that will cause a "toString()" will make it not available for reuse in Strings...

Verifications

Using httpRequest, I got MalformedURLException with a clearly well-formed URL... I made sure the URL was in String format and has the protocol...

java.net.MalformedURLException: no protocol: https://github.company.com/org/repo

Upvotes: 2

Views: 5155

Answers (1)

yong
yong

Reputation: 13722

You can use the username/password inside withCredentials block for any times. But keep in mind, the username/password can only survive inside withCredentials block.

I used the same username/password for twice in following code and it worked well.

node('docker') {
  withCredentials([steps.usernamePassword(
      credentialsId: 'ba2e4f46-56f1-4467-ae97-17b356d7f854',
      usernameVariable: 'JENKINS_USERNAME',
      passwordVariable: 'JENKINS_PASSWORD')]) {

     def log = sh(
         returnStdout: true,
         script: "curl -u ${env.JENKINS_USERNAME}:${env.JENKINS_PASSWORD} -k ${env.BUILD_URL}" + 'consoleText').trim()

     def pipelineSteps = sh(
         returnStdout: true,
         script: "curl -u ${env.JENKINS_USERNAME}:${env.JENKINS_PASSWORD} -k ${env.BUILD_URL}" + 'flowGraphTable').trim()

     echo '\n## build log ##\n' + log

     echo '\n## pipelineSteps ##\n' + pipelineSteps
  }

  echo "JENKINS_USERNAME: ${env.JENKINS_USERNAME}" 
  // print JENKINS_USERNAME: null 
  // because JENKINS_USERNAME's lifecycle is limited inside withCredentials blok.      
}

Another issue in your code, if you did not specify option returnStdout: true for step sh, it should return null. Example: def output = sh('command'), output will be null

Upvotes: 1

Related Questions