10

I'd like to use a withCredentials() block in a shared-variable ("vars/") script rather than directly in the Jenkins pipeline because this is a lower-level semantic of a particular library, and also may or may not be required depending on the situation. However, withCredentials (or, at least, that signature of it) doesn't appear to be in scope.

script:

def credentials = [
    [$class: 'UsernamePasswordMultiBinding', credentialsId: '6a55c310-aaf9-4822-bf41-5500cd82af4e', passwordVariable: 'GERRIT_PASSWORD', usernameVariable: 'GERRIT_USERNAME'],
    [$class: 'StringBinding', credentialsId: 'SVC_SWREGISTRY_PASSWORD', variable: 'SVC_SWREGISTRY_PASSWORD']
]

withCredentials(credentials) {
// ...
}

Console:

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: BuildagentInstallAndRun.withCredentials() is applicable for argument types: (java.util.ArrayList, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [[[$class:UsernamePasswordMultiBinding, credentialsId:6a55c310-aaf9-4822-bf41-5500cd82af4e, ...], ...], ...]

Has anyone had any success with this?

Dustin Oprea
  • 9,673
  • 13
  • 65
  • 105
  • You probably need to import the credentials class or wrap it inside of pipeline code. I have not done something like the former before, but the latter is well documented. – Matthew Schuchard Jul 14 '18 at 12:52

3 Answers3

7

I'm using a shared library rather than a shared variable, but I guess it is a similar situation. I'm not using the $class parameter, but i'm calling directly one of the functions suggested by the pipeline snippet generator. You can have a list here. In the example below, I use the usernameColonPassword binding. In the pipeline, I instantiate the class utilities and I pass this to the constructor. Then, in the library, I use the step object to access the pipeline steps (such as withCredentials or usernameColonPassword).

class Utilities implements Serializable {
    def steps
    Utilities(steps) {
        this.steps = steps
    }
    def doArchiveToNexus(String credentials, String artifact, String artifact_registry_path){
        try {
            this.steps.withCredentials([steps.usernameColonPassword(credentialsId: credentials, variable: 'JENKINS_USER')]) {
                this.steps.sh "curl --user " + '${JENKINS_USER}' + " --upload-file ${artifact} ${artifact_registry_path}"
            }
        } catch (error){
            this.steps.echo error.getMessage()
            throw error
        }
    }
}
Fabio
  • 491
  • 3
  • 10
  • I do the same and I have to declare a constructor with 2 parameters: 'steps' and 'env'. Then for using variable JENKINS_USER I have to write "${env.JENKINS_USER}" instead of '${JENKINS_USER}'. Otherwise it doesn't work. – Max Nov 15 '19 at 09:38
  • @Max you can use variable JENKINS_USER like "${this.steps.env.JENKINS_USER}", therefore 'env' parameter can be omited – dalang Feb 09 '23 at 06:26
5

You can try following:

import jenkins.model.*

credentialsId = '6a55c310-aaf9-4822-bf41-5500cd82af4e'

def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
  com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, Jenkins.instance, null, null ).find{
    it.id == credentialsId}

println creds.username 
println creds.password

But it is not secure, everything will be in console log

Bulat
  • 301
  • 3
  • 5
2

I was able to obtain credentials inside the shared library with proper passwords masking with such code:

class Utilities implements Serializable {
def steps
Utilities(steps) {
    this.steps = steps
}
def execute() {
    this.steps.withCredentials(
            bindings: [
                this.steps.usernameColonPassword(
                    credentialsId: this.credentialsId, 
                    variable: "unameColonPwd")
            ]) {
        this.steps.sh "echo {this.steps.env.unameColonPwd}"
    }
}
foneox
  • 21
  • 1