One InfoSec requirement I've seen with several clients is a password change that must happen every ~30 days for all enterprise user accounts and service accounts. Since we've been using service accounts to reach internal Git repositories, Jenkins, OpenShift, and several other resources, updating each account's password manually every month in all locations was becoming increasingly frustrating for application teams. So, we automated it.
The following script was written for connecting to Git repos from Jenkins and OpenShift, and is included as a pipeline library in Jenkins so that all teams can import it. The script takes as parameters a service account username, and optionally a folder inside Jenkins, the length of the password to be created, and the directory service (Active Directory or LDAP, in this case). Then:
- It looks for the credential in Jenkins by ID provided, either at the folder level if you provide a folder name, or at the global level.
- If this credential exists in Jenkins, it creates a randomized password.
- It updates this password in AD/LDAP.
- It updates this password in the Jenkins credential.
- It updates the corresponding secret in OpenShift.
CredentialUtils.groovy
You'll need to store this script in a repo somewhere that is accessible from the Jenkins master.
Include script as pipeline library in Jenkins
You can include this script either at the global level in your Jenkins master, or in any folder in Jenkins.
Under "Pipeline Libraries" on the Configure page, click on "Add."
Add your credential-rotation script with whatever SCM you're using. You can give it any name -- this library name ("jenkins-creds-util" in my example) is what will be called from any Jenkins pipelines that are importing it.
Create your service account credential in Jenkins
If you haven't already, you'll need to add a credential in Jenkins for your service account. You can do this at either the global level of your Jenkins master or at the folder level.
Click on Credentials in the sidebar. Click on Folder below that when it appears in the sidebar. Then click on Global credentials (unrestricted) in the center to see a list of credentials saved in your folder on the Jenkins master.
Click on Add Credentials in the sidebar, and choose Username with password and scope Global. Enter in your service account's username and password. In the ID box, enter the same username. Click OK.
Create a scheduled pipeline to rotate credential
You'll need a pipeline in Jenkins that's scheduled to run every ~30 days that will call the CredentialUtils.groovy script for your service account. Make sure that if you added the pipeline library at the folder level, that you create this pipeline within the same folder.
Go to your team's folder in Jenkins and click New Item in the sidebar. Choose Pipeline and give it whatever name you like. On the Configure page for your new pipeline, you'll want to set a schedule for how often it runs by checking Build periodically under Build Triggers. I've set it to run every 15 days by entering H 10 1,15 * * in the scheduler. If you need help writing your own cron schedule, Crontab Guru is a good place to start.
In the "Pipeline Script" section of the Configure page, paste the below Jenkinsfile:
Customize pipeline for your team
If you don't need to update a source secret in OpenShift, you can remove the changeGitSecret method and the project, serviceAccount, and clusterAPIURL variables.
If you do need to update a source secret in OpenShift, there is one extra thing you'll need to set up. Your Jenkins master needs to contain a "secret text" credential with an OpenShift service account token for logging into the OpenShift cluster. More info about that here. The name of this credential in Jenkins will be the serviceAccount variable in the script above.
Here are all the variables you'll need to update in the above pipeline:
- username -- the username for your service account in LDAP whose password you will be rotating
- project -- the OpenShift project name where you build your microservices
- serviceAccount -- the Jenkins credential that logs into the OpenShift cluster
- folderName -- this is the folder location of your credential in Jenkins (not required if credential is stored at the global level)
- to find this, go to your credential and append "api/json?pretty=true" (for example, https://jenkins.com/job/_____/job/credentials/store/folder/domain/_/credential/<credential-name>/api/json?pretty=true)
- search for "fullName" and copy everything before "/folder/_/{credential-name}"
- so if you see "fullName" : "folder1/folder2/folder/_/<credential-name>"
- your folder name becomes "folder1/folder2"
Running your rotation pipeline
Once you've set up your pipeline, click Save.
You can either manually run it by clicking Build Now or you can wait until the dates specified in the cron schedule when it will automatically run.
Note: Keep in mind during testing that Active Directory usually limits updating your password to once every 24 hours.