-
Bug
-
Resolution: Fixed
-
Major
-
Jenkins 2.86 (jenkinsci/jenkins docker image)
pipeline-input-step 2.8
credentials-binding 1.13
credentials 2.1.16
-
-
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.
- is related to
-
JENKINS-44772 User Scoped credentials are not used by the "withCredentials" pipeline step
- Open
-
JENKINS-38963 User-scoped credentials cannot be looked up in pipeline
- Resolved
- relates to
-
JENKINS-59109 Allow user scoped credentials to be used by build step
- Open
-
JENKINS-58170 Allow credential parameters to shadow credential ids in lookup
- Resolved
- links to