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

Cannot use user-scoped credentials from pipeline input step parameters

XMLWordPrintable

    • pipeline-input-step 2.11

      A pipeline with an input step that has credential parameters will allow a user to select user-scoped credentials which don't work correctly with the withCredentials step later.

      To reproduce, create a user-scoped credential and the following pipeline

      properties([
          parameters([
              credentials(name: 'creds_param')
          ])
      ])
      
      
      stage('example'){
          node {
              withCredentials([string(credentialsId: '${creds_param}', variable: 'SECRET')]) {
                  sh 'echo "this works: $SECRET"'
              }
      
              input([
                  message: 'input?', 
                  submitterParameter: 'approver',
                  parameters: [
                      credentials(name: 'input_creds_param')
                  ]
              ])
          
              withCredentials([string(credentialsId: '${input_creds_param}', variable: 'SECRET')]) {
                  sh 'echo "this does not work: $SECRET"'
              }
         }
      }
      

      Which produces this output when built:

      Started by user ben
      [Pipeline] properties
      [Pipeline] stage
      [Pipeline] { (example)
      [Pipeline] node
      Running on Jenkins in /var/jenkins_home/workspace/pipeline-test
      [Pipeline] {
      [Pipeline] withCredentials
      [Pipeline] {
      [Pipeline] sh
      [pipeline-test] Running shell script
      + echo this works: ****
      this works: ****
      [Pipeline] }
      [Pipeline] // withCredentials
      [Pipeline] input
      Input requested
      Approved by ben
      [Pipeline] withCredentials
      [Pipeline] // withCredentials
      [Pipeline] }
      [Pipeline] // node
      [Pipeline] }
      [Pipeline] // stage
      [Pipeline] End of Pipeline
      org.jenkinsci.plugins.credentialsbinding.impl.CredentialNotFoundException: ${input_creds_param}
      	at org.jenkinsci.plugins.credentialsbinding.MultiBinding.getCredentials(MultiBinding.java:153)
      	at org.jenkinsci.plugins.credentialsbinding.impl.StringBinding.bindSingle(StringBinding.java:62)
      	at org.jenkinsci.plugins.credentialsbinding.Binding.bind(Binding.java:150)
      	at org.jenkinsci.plugins.credentialsbinding.impl.BindingStep$Execution.start(BindingStep.java:114)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:224)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:150)
      	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:108)
      	at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1278)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1172)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:810)
      	at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46)
      	at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1278)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1172)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
      	at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:19)
      	at WorkflowScript.run(WorkflowScript:22)
      	at ___cps.transform___(Native Method)
      	at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
      	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
      	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
      	at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
      	at com.cloudbees.groovy.cps.Next.step(Next.java:83)
      	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
      	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
      	at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
      	at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
      	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:330)
      	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:82)
      	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:242)
      	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:230)
      	at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      	at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
      	at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      	at java.lang.Thread.run(Thread.java:748)
      Finished: FAILURE
      

      I think the problem is with how the credentials plugin finds the credentials from parameters. It looks, if the credential id starts with ${ and ends with } then it looks for a ParametersAction on the run (see CredentialsProvider lines 882-892)

      Then it includes the user-scoped credentials of the user that triggered the build as candidates for the credential id specified (see CredentialsProvider lines 912-922)

      Two problems I see (there may be more):

      • The input step does not create a ParametersAction on the run, so the credentials plugin won't find it.
      • The user that triggered the build is not necessarily the user that answered the input question and provided credential parameters, so the credential candidates won't be the right ones if we just use the user that triggered the build.

      In case it's necessary to provide justification for why the user that triggered the build might not be the person answering the input, consider this scenario: The build is triggered by an SCM change in a multibranch pipeline on the master/default branch. Maybe it's a tagged release that then builds, deploys to some staging environment, runs integration tests, and then waits for confirmation and credentials to deploy to a production environment. That user that approves and provides their personal credentials for production is not the user that triggered the build (SCM was the original cause).

      I commented on JENKINS-38963 about this too, but I thought this issue is more specific about how input credential parameters work with user-scoped credentials and the credential binding steps.

            jvz Matt Sicker
            b_dean Ben Dean
            Votes:
            12 Vote for this issue
            Watchers:
            19 Start watching this issue

              Created:
              Updated:
              Resolved: