Workflow Integration for Credentials Binding Plugin

Workflow steps that do something specific, like check out SCM sources, will often have a way to specify a credentialsId to pass in secret credentials appropriate to that task. However there was an unmet need to manage secrets using the Jenkins web UI (the usual Credentials link) but access them from a freeform sh or bat build step, where the secret (such as a server password) is used in the middle of a system shell script.

For freestyle projects this was handled with the Credentials Binding plugin, in some cases also with the help of the Plain Credentials plugin. I have just released an update to Credentials Binding that adds a new Workflow step, withCredentials, offering similar functionality. For example:

node {
  withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'mylogin',
                    usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
    sh '''
      set +x
      curl -u $USERNAME:$PASSWORD https://private.server/ > output
    '''
  }
}

As usual, you can use the Snippet Generator to get a hint about the syntax to use. But to make this comfortable to write by hand, and easier to read the result, it is also desirable to have short, memorable credentialsIds, rather than the random UUIDs you usually get. For this reason I also enhanced the Credentials plugin and Plain Credentials plugins to let you pick an ID when you create credentials. (A similar change in the SSH Credentials plugin is currently awaiting release, though there is not currently any way to access an SSH private key using Credentials Binding anyway; use a Secret File from Plain Credentials in the meantime.)

As with the freestyle build wrapper, if you bind an environment variable to a secret file, it will get deleted from your slave’s disk at the end of the step. Because withCredentials is built for Workflow, this happens even if Jenkins is restarted in the middle of the block.

 

Jesse Glick
Developer
CloudBees

 

Blog Categories: 

Comments

I like the addition of the withCredentials build step, I think there might be a small mistake with the documentation, I can only get this to work by using env.USERNAME

If you are using the variable as an environment variable, for example inside a shell or batch script, you would use shell- or batch-specific means to access it, for example `$USERNAME` or `%USERNAME%`. If you are using it directly from the Groovy script, you must use `env.USERNAME`. The example uses it inside a shell script, so uses `$USERNAME`.

I am trying below code on script console to fetch id and password in my workflow script withCredentials([[$class:'UsernamePasswordMultiBinding', credentialsId:'my_defined_id', usernameVariable:'USERNAME', passwordVariable:'PASSWORD']]){ echo env.USERNAME} I am getting below error groovy.lang.MissingMethodException: No signature of method: Script1.withCredentials() is applicable for argument types: (java.util.ArrayList, Script1$_run_closure1) values: [[[$class:UsernamePasswordMultiBinding, credentialsId:b0b2c37c-1b6f-4382-a9cf-73a427fb8d70, ...]], ...] can someone please help

You cannot run Workflow code from the script console.

I am trying the same code in workflow but getting below error hudson.remoting.RemotingSystemException: java.io.IOException: Remote call on OperationsCenter at http://199.63.86.103:8888/ failed at hudson.remoting.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:195) How to resolve it. Actually I want to store the username and password as environment variable and want to use it in workflow script, the password should be masked in console output. is there anyway to perform this ?

The RemotingSystemException sounds like a CJOC issue, perhaps. File a support ticket about it. This blog is not a good place to request support on bugs.

I am getting the below error when I use withCredentials inside workflow script. java.lang.NoSuchMethodError: No such DSL method withCredentials found among [archive, bat, build, catchError, checkout, checkpoint, deleteDir, dir, dockerFingerprintFrom, dockerFingerprintRun, echo, error, fileExists, git, input, load, mail, node, parallel, properties, pwd, readFile, retry, sh, sleep, sshagent, stage, stash, step, svn, timeout, tool, triggerRemoteJob, unarchive, unstash, waitUntil, withDockerContainer, withDockerRegistry, withDockerServer, withEnv, wrap, writeFile, ws] Please advise

Kumaresan, You need to ensure that this method is enclosed in a node(){} block.

I have a similar block, like this: ------------------ withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: JP_MechIdCredentials, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { println sh(returnStdout:true, script:"./scpauto \"$USERNAME\" \"$PASSWORD\" \"$JP_JavadocJarHost\" \"$javadocJarPath\" \"/tmp\"") println sh(returnStdout:true, script:"./sshauto \"$USERNAME\" \"$PASSWORD\" \"$JP_JavadocJarHost\" \"cd ${JP_JavadocRootRemotePath}; rm -rf ${versionNumber}; mkdir ${versionNumber}; jar xvf /tmp/${baseFileName}\"") } ------------- The "scpauto" and "sshauto" scripts are just short "expect" scripts, to execute scp and ssh interactively, to send the password. When I run this, I see the following: -------------------- [Pipeline] withCredentials [Pipeline] { [Pipeline] sh [usl-parent] Running shell script [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // dir [Pipeline] sh [workspace@2] Running shell script + git log -5 --date=short '--pretty=format:%cN: %cd : %s' [Pipeline] sh [workspace@2] Running shell script + git log -5 --pretty=format:%cE + sort -u [Pipeline] sh [workspace@2] Running shell script + git rev-parse HEAD [Pipeline] echo commitSHA[5ce23a5847a3253a8cc155c22205374e980f6292] creds[121447d5-0fe4-470d-b785-6ce88225ef01] [Pipeline] step Unable to expand commit SHA value with org.jenkinsci.plugins.workflow.job.WorkflowRun Notified Stash for commit with id 5ce23a5847a3253a8cc155c22205374e980f6292 [Pipeline] q [Q Step] Q successfully sent to q_rooms_dk068x1479493906353 [Pipeline] emailext An attempt to send an e-mail to empty list of recipients, ignored. [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline [DOSSIER] Response Code: 0 [DOSSIER] Backup file created: ... [DOSSIER] Seconds to input data: 0 java.io.NotSerializableException: sun.nio.fs.UnixPath at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860) ... Caused by: an exception which occurred: in field locals in field caller ... Finished: FAILURE ----------------------- Curiously, I've also tried to get this to work with the "sshagent" plugin, using a registered key instead of a password, but I get virtually the same "NotSerializableException: sun.nio.fs.UnixPath" exception.

I was able to resolve the problem I reported earlier. The problem was really due to lines that occurred before the block in question, where I created a "Path" variable. The stacktrace never pointed here, and it never occurred to me that "Path" is the base class for UnixPath. The solution to this problem was strange, but somewhat understandable. I simply assigned "null" to the Path variable after I was done with it.

Add new comment