Search code examples
jenkinsgroovyjenkins-pipelinejenkins-pluginsjenkins-groovy

withCredentials failing for credential type(userNamePassword vs stringCredential)


I am trying to access Grafana from a Jenkins pipeline(withCredentials + httpRequest).

This is how the credential(the Grafana's actual admin username, and password) looks in Jenkins: enter image description here

The partial pipeline code:

script.withCredentials([script.string(
                    credentialsId: "${credentialsEnvironment}",
                    variable: 'usernamePassword')
            ]) {

                String auth = "${script.usernamePassword}".bytes.encodeBase64().toString()
                Map params = defaultArgs + httpParams
                def response = []
                try {
                    response = script.httpRequest(
                            params +
                            [
                                url: "${apiEndpoint}/${url}",
                                customHeaders: [[name: 'Authorization', value: "Basic ${auth}"]]
                            ]
                    )

                    if (response && (response.status != 200 && response.status != 201)) {
                        script.echo "Response status: ${response.status}"
                        script.echo "Response message: ${response.content}"
                    }
                    return response
                } catch (ex) {
                    LogUtil.echoStacktraceToScript(script, ex)
                    throw new ObservabilityException("Error: An exception occured when sending request with params: ${params}", ex)
                }
            }

The exception:

10:49:56  credentialsEnvironment: sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
10:49:56  [Pipeline] withCredentials
10:49:56  [Pipeline] // withCredentials
10:49:56  [Pipeline] echo
10:49:56  org.jenkinsci.plugins.credentialsbinding.impl.CredentialNotFoundException: Credentials 'sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
10:49:56    at org.jenkinsci.plugins.credentialsbinding.MultiBinding.getCredentials(MultiBinding.java:208)
10:49:56    at org.jenkinsci.plugins.credentialsbinding.impl.StringBinding.bindSingle(StringBinding.java:57)
10:49:56    at org.jenkinsci.plugins.credentialsbinding.Binding.bind(Binding.java:149)
10:49:56    at org.jenkinsci.plugins.credentialsbinding.impl.BindingStep$Execution2.doStart(BindingStep.java:132)
10:49:56    at org.jenkinsci.plugins.workflow.steps.GeneralNonBlockingStepExecution.lambda$run$0(GeneralNonBlockingStepExecution.java:77)
10:49:56    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
10:49:56    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
10:49:56    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
10:49:56    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
10:49:56    at java.base/java.lang.Thread.run(Thread.java:829)

What exactly am I missing here?

------Edit-1--------

I modified the code but now I am clueless about how to pass the username, and password as the httpRequest doc. says nothing about it.

script.println "Attempting to use ${credentialsEnvironment}"

            script.withCredentials([script.usernamePassword(
                    credentialsId: "${credentialsEnvironment}",
                    passwordVariable: 'passw', usernameVariable: 'user')
            ]) {

                script.println "user: ${script.user}"
                String auth = "${script.user}".bytes.encodeBase64().toString()
                script.println "auth: ${auth}"

                Map params = defaultArgs + httpParams
                def response = []
                try {
                    response = script.httpRequest(
                            params +
                            [
                                url: "${apiEndpoint}/${url}",
                                customHeaders: [[name: 'Authorization', value: "Basic ${auth}"]]
                            ]
                    )

                    if (response && (response.status != 200 && response.status != 201)) {
                        script.echo "Response status: ${response.status}"
                        script.echo "Response message: ${response.content}"
                    }
                    return response
                } catch (ex) {
                    LogUtil.echoStacktraceToScript(script, ex)
                    throw new ObservabilityException("Error: An exception occured when sending request with params: ${params}", ex)
                }
            }

Output:

credentialsEnvironment: sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
13:05:52  [Pipeline] echo
13:05:52  Attempting to use sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
13:05:52  [Pipeline] withCredentials
13:05:52  Masking supported pattern matches of $user or $passw
13:05:52  [Pipeline] {
13:05:52  [Pipeline] echo
13:05:52  user: ****
13:05:52  [Pipeline] echo
13:05:52  auth: YWRtaW50ZXN0
13:05:52  [Pipeline] httpRequest
13:05:52  HttpMethod: GET
13:05:52  URL: https://plg-grafana-sb-1365-kraken-monitoring.apps.scp-west-zone01-z01.net/api/folders
13:05:52  Content-Type: application/json
13:05:52  Accept: application/json
13:05:52  Authorization: *****
13:05:52  Sending request to url: https://plg-grafana-sb-1365-kraken-monitoring.apps.scp-west-zone01-z01.net/api/folders
13:05:52  Response Code: HTTP/1.1 401 Unauthorized
13:05:52  Success: Status code 401 is in the accepted range: 100:500
13:05:52  [Pipeline] echo
13:05:52  Response status: 401
13:05:52  [Pipeline] echo
13:05:52  Response message: {"message":"Invalid Basic Auth Header","traceID":""}

Solution

  • You don`t need withCredentials with httpRequest plugin; just pass the credential id. Try something like this:

    httpRequest url:"${apiEndpoint}/${url}", ..., authentication: credentialsEnvironment
    

    See how to use httpRequest in Jenkinsfile pipeline with basic auth