How to mask credentials in Jenkins Platform.

Pre-requisites:

You may have a list of passwords, or other confidential files or strings which you want to be used by a job but which should not be kept in its SCM, or even visible from its config.xml. Saving these files on the server and referring to them by absolute path requires you to have a server login, and does not work on slaves. These plugins together gives you an easy way to package up all a job’s secret files and passwords and access them using a single environment variable during the build.

The following content will give an idea on how to use the username and password masking feature of the credentials binding plugin, in order to keep your credentials masked in console logs which enhances the security aspect of your project.

Steps:

  1. After installing the plugin, you will now have a new option under “Build Environment” which is called “Use secret text(s) or file(s)”, check it and a new box will appear named “Bindings”. Under it, the drop down called “Add “ will be visible.

2. Click on Add and choose “Username and password (separated)”

3. We have to add the credentials needed for the project. Select ‘Add’ → ‘Jenkins’ in order to add global credentials.

To maximize security, credentials configured in Jenkins are stored in an encrypted form.

4. Set ‘Global Credentials’ under domain and ‘Username and Password’ under kind. The scope can be set according to how the credentials should be available for usage.

  • Global Scope — This is the default scope. Global scope credentials are available to all jobs within Jenkins, so that all Jenkins jobs are allowed to use global-scoped credentials.
  • System Scope — These credentials are only exposed to the Jenkins system and background tasks where the Jenkins instance itself is using the credentials, and will not be available to jobs within Jenkins. Unlike the global scope, this significantly restricts where the credential can be used, thereby providing a higher degree of confidentiality to the credential

5. After adding and selecting the global credentials, you can set the variables to separately identify the username and the password of the selected credentials.

6. The variables can now be used for shell/ batch scripts as needed.

Shell example:

1 echo $USER

2 echo $PASS

Windows batch example:

1 mvn clean test -Pscenario -Dsuite="TestSuite" -Duser="%USER%" -Dpassword="%PASS%"

The username and password in the console output will be masked and shown as follows:

Method 2 — Mask Passwords Plugin

Pre-requisites: Mask Passwords Plugin (https://plugins.jenkins.io/mask-passwords/): This plugin allows masking passwords that may appear in the console, including the ones defined as build parameters.

  • The difference between the 2 methods is that Mask Passwords plugin requires you to provide the passwords within the build environment itself while the credential binding method takes use of the Jenkins Credentials store.
  • The end result of both will be to mask the passwords which will be visible in plain text if such mechanism is not applied.

However, there is a security vulnerability found on this plugin which goes against its own intention where Plain text passwords shown in global configuration form fields.

SECURITY-157 / CVE-2019–10370

Mask Passwords Plugin allows specifying passwords to be provided to builds in the global Jenkins configuration. While the passwords stored are encrypted on disk, they are transmitted in plain text as part of the configuration form. This can result in exposure of the password through browser extensions, cross-site scripting vulnerabilities, and similar situations.

CVE Details and severity: https://nvd.nist.gov/vuln/detail/CVE-2019-10370

Conclusion

The research on the matter made it clear that Credentials Binding plugin seemed to be the popular and most used technique with 248640 installs while mask password plugin only having 16939 recorded installs. The vulnerability CVE-2019–10370 and not having maintainers bound to the mask password plugin are also red flags . Thus, the method 1: Credentials binding can be concluded as the better fit for the task with higher security and more features.

Masking Credentials in a Declarative Pipeline Project

The conclusion of using the Credentials Binding method for freestyle project can be extended for the declarative pipeline project as well. With the plugin set used for credentials biding, it paves the way for 2 potential methods to incorporate the credentials masking feature in a pipeline based project. In the Performance platform, we use the pipeline structure to onboard a project to Jenkins:

Pre-requisites:

  • Having the required credentials set in Credentials Manager.
  • Navigate to Manage Jenkins → Manage Credentials → Jenkins Credentials → System → Global credentials (unrestricted)
  • Set ‘Global Credentials’ under domain and set ‘Username and Password’ under kind. The scope can be set according to how the credentials should be available for usage. (Screenshots attached under “Masking Credentials in a Freestyle Project > Method 1 > Step4”)

Method 1 — Setting the Credentials Variable in the Environment Directive

1. The credentials we have set in Jenkins as mentioned in the pre-requisites, can now be assigned to a variable. This should be done within the environment directive of the Jenkinsfile.

pipeline { environment{

// The id of the test credentials added to Jenkins credentials manager were used. It automatically creates the 3 variables $TESTCREDS_CREDS $TESTCREDS_USR and $TESTCREDS_PSW

TESTCREDS = credentials('test-credentials') } }

test-credentials is the ID we assign when we add our username and password to Jenkins as a Global credential as shown below.

When we assign a variable to the set credentials, it will automatically set 3 variables for user convenience:

  • TESTCREDS — contains a username and a password separated by a colon in the format username:password
  • TESTCREDS_USR — an additional variable containing the username component only.
  • TESTCREDS_PSW — an additional variable containing the password component only.

The _USR and _PSW will be automatically set as suffixes for your username and password respectively.

2. Now we can use the above variables anywhere in the Jenkinsfile where the username and and password are required. To maintain the security and anonymity of these credentials, if the job displays the value of these credential variables from within the Pipeline (e.g. echo $TESTCREDS_PSW ), Jenkins only returns the value “****” to reduce the risk of loosing secret information.

Thus, we can achieve our goal by executing the performance test as below:

1 2 3 4 5 6 7 8 9 10 stage('Execute Performance Test') { steps { container('distributed-jmeter-master'){ sh 'echo ===============Start maven build execution=======================' sh 'echo ${jenkinsSlaveNodes}' sh '''mvn clean install -DjenkinsSlaveNodes=${jenkinsSlaveNodes} -DscriptName=${scriptName} -Dusername=${TESTCREDS_USR} -Dpassword=${TESTCREDS_PSW}''' sh 'echo ===============Finishing maven build execution=======================' } } }

Now the credentials will be masked and will be shown in the log as follows:

Method 2 — Define Variables in “withcredentials” Block

With this method, we do not have to use the environment directive. We can directly use the credentials binding method, withcredentials() when we need to mask sensitive data we have under Jenkins global credentials.

stage('Execute Performance Test') { steps { container('manula-cont'){ sh 'echo ===============Start maven build execution=======================' withCredentials([usernamePassword(credentialsId: 'test-credentials', usernameVariable: 'USERNAME_VAR', passwordVariable: 'PASSWORD_VAR')]) { sh '''mvn clean install -DjenkinsSlaves=${jenkinsSlaves} -DscriptName=${scriptName} -Dusername=${USERNAME_VAR} -Dpassword=${PASSWORD_VAR}''' } } }

The major disadvantage with this methodology would be that the password will be masked only in withCredentials blocks. Thus, if there are multiple masking to do, there will be repetitive code which will not adhere to coding best practices. However the same end goal of masking credentials can be achieved.

Quality Engineer specializing in Performance Engineering process. Cyber Security Researcher. Reading for MSc. in Big Data Analytics.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store