docwhat's avatardocwhat's blog

User credentials in a Jenkins pipeline

Photo by Crystal Kwok source

The Credentials User Guide implies you can use user credentials. These are credentials that are owned and managed by a user instead of the administrator or the owner of a folder.

The guide explains how to use them with Freestyle jobs (classic Jenkins jobs) but not how to use them with the newer declarative pipeline jobs.

In this post, I’ll show you how to:

  • Set up a job to ask for credentials when triggered.
  • Allow users to provide their user credentials as a parameter.
  • Configure the pipeline job to use the passed in credentials.

Setup Jenkins

As a normal user you shouldn’t have to worry about this part. If the steps below don’t work, then you may have to bring this to the attention of your Jenkins administrator.

To use user credentials the user kicking off the build needs to have the Credentials/UseOwn permission.

By default this is inherited by Item/Build (AKA Job/Build) but not recursively!

This means that if “MyGroup” has the permission Item/Build then the user isn’t given Credentials/UseOwn. You have to give the user Item/Build directly.

Managing permissions without groups is hard. Instead, the administrator can run this groovy (via the Script Console or via the CLI):

// Give everyone "Credentials/UseOwn"
System.setProperty("com.cloudbees.plugins.credentials.UseOwnPermission", "true")

To make it permanent the administrator should put it in an init.groovy.d file.

Steps

As a normal end user of Jenkins, you can put these steps in your declarative pipeline (e.g., Jenkinsfile):

  1. Add a parameters section if one doesn’t exist already.

  2. Within the parameters section, add a credentials section.

    /* EXAMPLE */
    parameters {
        credentials(
            credentialType: 'com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl',
            defaultValue: '',
            description: 'The credentials needed to deploy.',
            name: 'deployCredentialsId',
            required: true
        )
    }
  3. Within a steps section, use the withCredentials() method, using the credentialsId specified above wrapped with ${...}.

    /* EXAMPLE */
    steps {
        withCredentials([usernamePassword(
            credentialsId: '${deployCredentialsId}',
            usernameVariable: 'DEPLOY_USERNAME',
            passwordVariable: 'DEPLOY_PASSWORD',
        )]) {
            sh './my-command.bash --username="${DEPLOY_USERNAME}" --password="${DEPLOY_PASSWORD}"'
        }
    }

Caveats

withCredentials can only use the user credentials if the user kicks off the build.

Builds triggered remotely (via URL) or via a cron specification won’t work.

This is because the build runs (by default) as ACL.SYSTEM. ACL.SYSTEM doesn’t have permission to read any user’s credentials.

The ${<parameter_name>} is a bit of magic that fetches the credentials as stored in the parameter, by passing the permission check.

Edit on GitHub