How to manage sensitive credentials?

Issue

Some companies have a strong security policy.

Make Credentials available for users can make your entity/company in trouble because of Security vulnerabilities. Indeed, any user having access to credentials can expose them.
Examples of security vulnerabilities:

  • A malicious unit test can steal many the credentials used during the build (read maven settings, access git credentials…)
  • Credentials locked down to a specific plugin could be leaked using the locked down plugin (e.g. git) to connect to a rogue endpoint

Jenkins credentials can be used by plugins and plugins can expose these credentials in the build environment (environment variable…); it’s then easy to leak the credentials with a bat/sh command (wget, email…). Due to this design, credentials can be leaked by malicious users.

Environment

Resolution

Credentials can be secured being located with scripts/tasks that don’t expose high level APIs that don’t allow to see the credentials being used. These secured scripts/tasks can be secured with CloudBees solutions:

  • Remove the permission(1) for application team members to create/edit their pipelines & jobs without control from the “Jenkins admins in charge of ensuring security”
    • Templatize the jobs(2)
      • Restrict the available types of job so that application teams can only create templatized jobs(3)
      • Use pipeline jobs stored in a git repo owned by Jenkins admins on which the application teams submits changes through pull requests(4)
        Note: The Jenkins admins can ensure that the pipeline script is not malicious and is not leaking credentials.
      • The use of marker files is highly recommended(4)(5)
  • Locate these “atomic scripts” in dedicated folders secured by CloudBees RBAC(1) so that only Jenkins admins can modify these scripts and define the credentials at the folder level

Remark

The use of the Mask Passwords Plugin(6) and/or Credentials Binding Plugin(7) remains recommended.

  • Benefits: prevent secrets leaks in the logs
  • Limits: don’t protect against pipeline script code that would decide to leak the password outside of Jenkins

Workaround

The Mask Passwords Plugin will mask passwords (from printing to the console) that are statically defined within the project/job. But if your password is retrieved dynamically, here is how you can temporarily prevent the password from leaking into the console log.

  1. Ensure you have Mask Passwords Plugin installed.
  2. Create Freestyle project and name it test-mask-password.
  3. Under the Build Environment heading select Mask passwords and regexes.
  4. Create a Name/Password Pair, e.g. Name: PASS, Password: a-dummy-password-will-suffice.
  5. Select a Regular Expression and add password.*. This is a workaround where we mask out all text strings that may precede the $PASS environment variable (in our example).
  6. Add build step and select Execute shell.
  7. Use the following script as an example (with a following explanation).
printenv PASS

(
  printf "PASS=" > /tmp/password.env
  openssl rand -base64 12 >> /tmp/password.env
  . /tmp/password.env > /dev/null 2>&1
  printenv PASS    # avoid this leak!
  echo $PASS       # avoid this leak!
  echo mvn package -Dpassword=$PASS
  rm /tmp/password.env
)

echo $PASS

Notice:

  • the first printenv statement demonstrates the PASS variable is masked out
  • create a subshell by encapsulating the following statements in parenthesis
  • let openssl rand -base64 12 represents a dynamic password retrieval command or script
  • by writing to a file we avoid printing the password to standard output
  • we source the file and we redirect standard output to /dev/null
  • the second printenv will actually print out the password PASS to the console, here we’re demonstrating that within the subshell we have replaced the environment variable PASS and assigned it a new value (and it cannot be masked), you will need to avoid printing this!
  • the regex password.* mask will prevent the printing of the $PASS value
  • once the subshell is completed, note that the PASS environment variable is once again masked

References

(1) Role-Based Access Control Plugin
(2) Pipeline Job Templates
(3) How to restrict job types in folders?
(4) Custom Pipeline as Code Scripts (marker files)
(5) Ensuring Corporate Standards in Pipelines with Custom Marker Files
(6) Mask Passwords Plugin
(7) Credentials Binding Plugin

Have more questions?

0 Comments

Please sign in to leave a comment.