New year, new credentials! (well almost)
Not long ago, I (like most people), went down the rabbit hole of working around some Jenkins limitations. I was experiencing some issues of hitting identity provider API rate limits due to heavy API usage of Jenkins. After some experimenting, I found that using Jenkins API tokens for machine to machine communication instead of user credentials doesn't require identity provider authentication which significantly cuts down on hitting said rate limits. "This is great!", I thought.
Next up, I was looking into the the gojenkins client library to see if there were some built-in methods to allow me to do my own API token management and rotation to solve the issue above. And of course, it didn't exist. It was at this point I sat back and thought, "Really? No one has yet to implement a decent solution for managing Jenkins tokens/users yet? This is the most widely used CI server out there. Surely it has to exist..."
Sure, I was already aware of the vault-jenkins-plugin which allowed Jenkins to fetch secrets from Vault, but what about accessing Jenkins itself?! Nope, it didn't exist. I then began to think about all the work needed to solve this problem in a non-crufty way. First of which included some PR's to the gojenkins client library to add some API/User management methods to make the overall solution cleaner, as well as give back to the community so that they can automate all of their problems away as well.
I've built other plugins for products within the Hashicorp ecosystem before, such as Terraform, but never a Vault plugin. I thought this would be a good opportunity to learn more about the inner workings of Vault and fill this gap in the community.
Low and behold, I created the vault-plugin-secrets-jenkins project!
Yes. That is a glorious chicken sandwich and I'm leaving it.
I'm glad you asked!
Once installed, the vault plugin takes in a configuration of a "root" Jenkins user. Then on behalf of this user, Vault can create short lived users as well as short lived API tokens for the configured user!
Dude, it's almost 2022. Hardcoding credentials as environment variables is not the best way to handle secrets these days. Now you can just request/rotate your own dynamic credentials by integrating with Vault.
First detailed guidance/examples, you'll want to checkout the project README here, but while I have you, I'll show you some examples.
vault secrets enable -path=jenkins vault-plugin-secrets-jenkins Success! Enabled the vault-plugin-secrets-jenkins secrets engine at: jenkins/
vault write jenkins/config url=http://localhost:8080 username=admin password=admin Success! Data written to: jenkins/config
Bonus: The plugin validates your config before moving on 😁
vault read jenkins/tokens/mytoken Key Value --- ----- lease_id jenkins/tokens/mytoken/fJ57afQZMyXDcJnm74BgLLt8 lease_duration 5m lease_renewable true token 1184cb7b22c404efa1c293e9841b66f345 token_id 1c2864f3-4108-4417-807a-358357bc8432 token_name mytoken
vault write jenkins/users/myuser password=password fullname="Jenkins the Butler" email@example.com Key Value --- ----- lease_id jenkins/users/myuser/hTGbJhDFbAQpALv1FjJyJ4vz lease_duration 5m lease_renewable true email firstname.lastname@example.org fullname Jenkins the Butler username myuser
Woohoo! We now have automatically expiring users and tokens we can manage from our app and can give our pals over in information security some piece of mind that even if our credentials do leak, they'll be useless within just a couple of minutes. Pretty slick right?!
Thanks for taking the time to checkout my article!
(gifs of more chicken sandwiches are encouraged in the comments section)