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

Cannot use user-scoped credentials from pipeline input step parameters

    • 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.

          [JENKINS-47699] Cannot use user-scoped credentials from pipeline input step parameters

          Ben Dean added a comment -

          I made a couple PRs:

          The one for credentials-plugin in particular could use some attention from someone that knows Jenkins source code better than myself. Probably stephenconnolly. I'm sure you'll hate it as it is right now , but it does work on a local instance to make it so I can use a user-scoped CredentialsParameterValue in a withCredentials step (which calls CredentialsProvider#findCredentialById)

          Ben Dean added a comment - I made a couple PRs: jenkinsci/pipeline-input-step-plugin#19 jenkinsci/credentials-plugin#95 The one for credentials-plugin in particular could use some attention from someone that knows Jenkins source code better than myself. Probably stephenconnolly . I'm sure you'll hate it as it is right now , but it does work on a local instance to make it so I can use a user-scoped CredentialsParameterValue in a withCredentials step ( which calls CredentialsProvider#findCredentialById )

          Removing myself as assignee. My current work assignments do not provide sufficient bandwidth to review these issues and in the majority of cases I am only assigned by virtue of being the default assignee. For the credentials-api and scm-api related plugins I have permission to allocate time reviewing changes to these APIs themselves to ensure these APIs remain cohesive, but that can be handled through PR reviews rather than assigning issues in JIRA

          Stephen Connolly added a comment - Removing myself as assignee. My current work assignments do not provide sufficient bandwidth to review these issues and in the majority of cases I am only assigned by virtue of being the default assignee. For the credentials-api and scm-api related plugins I have permission to allocate time reviewing changes to these APIs themselves to ensure these APIs remain cohesive, but that can be handled through PR reviews rather than assigning issues in JIRA

          Devin Nusbaum added a comment -

          A fix for this issue was just released in Pipeline: Input Step Plugin version 2.11.

          Devin Nusbaum added a comment - A fix for this issue was just released in Pipeline: Input Step Plugin version 2.11.

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

              Created:
              Updated:
              Resolved: