First posted on Jenkins Chinese community

background

I learned that some of the teams in the industry were developing the DevOps platform based on Jenkins. However, the Jenkins based DevOps platform has to consider the management of credentials.

This paper discusses this problem and tries to find out a relatively reasonable management voucher scheme.

The initial scenario we had in mind might be something like this: After users add credentials to DevOps, DevOps synchronizes those credentials to Jenkins. The Jenkins task uses credentials stored on Jenkins, not on the DevOps platform.

But, if you think about it, there are the following problems:

  • There will be inconsistencies in the credential data between Jenkins and DevOps platforms.
  • There are some security risks. It is easy to get all passwords in clear text from the Jenkins script command line. One day Jenkins was injected, and all the credentials were stripped.
  • Jenkins high availability could not be implemented because credentials exist on the Jenkins Master machine.

So, is there a better way?

Desired goals

Set goals that we think are more reasonable, and then discuss how to achieve them. Here are my reasonable goals:

Users still manage their credentials in DevOps. But DevOps doesn’t need to sync their credentials to Jenkins. When the Jenkins task uses credentials, it gets them from DevOps.

implementation

The Credentials Binding Plugin is used in Jenkins Pipeline as follows:

withCredentials([usernameColonPassword(credentialsId: 'mylogin'.variable: 'USERPASS')]) {
    sh ''' curl -u "$USERPASS" https://private.server/ > output '''
  }
Copy the code

All the withCredentials method does is take the credentials with id myLogin from Jenkins’ list of credentials and assign the value to a variable named USERPASS. Next, you can use this variable in the closure.

Speaking of here, do not know whether the reader friend has already had the idea?

The idea is to implement something similar to the Credentials Binding Plugin, such as zWithCredentials (mentioned later). Unlike withCredentials, when zWithCredentials get credentials based on their ID, they do not get them from Jenkins, but from the DevOps platform.

Will encounter the pit

Need to adapt plugins that recognize Jenkins credentials only

The withCredentials method stores the contents of the credentials in variables, which can be used for most scenarios. But there is one scenario that cannot be satisfied. The parameter value must be the ID in the Jenkins credential management system. For example, the credentialsId parameter in the git step:

git branch: 'master'.    credentialsId: '12345-1234-4696-af25-123455'.    url: 'ssh://[email protected]:company/repo.git'
Copy the code

In this case, it is not possible to modify existing plug-ins. Because it would be too expensive.

So what to do?

The solution I came up with was to do some hacks in zWithCredentials. In addition to getting credentials from the DevOps platform, zWithCredentials also create a Jenkins credential in Jenkins. Delete the temporary voucher after Jenkins’ task is completed. This works with plugins that only recognize Jenkins credentials.

Encryption of the credentials themselves

DevOps platform needs to encrypt the credentials when storing them and transferring them to Jenkins. As for the use of encryption, to the reader to think.

summary

The above solution does little to change Jenkins itself, we decoupled Jenkins credential management from DevOps platform credential management with just one plug-in.

The idea is there. Specific how to implement, due to some reasons can not open source, although the implementation is not difficult. Please bear with me.

Finally, I hope to communicate with other students who have similar problems. Let’s see if we can come up with a better design.

Author: Zhai Zhijun