Issue
How can I create a Service Account to perform some Jenkins® actions like triggering builds but without being able to log in on the UI?
Notes aside
First of all, some key concepts:
-
Jenkins maintains its own list of internal Jenkins Users under
$JENKINS_HOME/users
. -
The directory
$JENKINS_HOME/users
is populated with all those Users that have logged in to Jenkins at least once, resulting in the combination of all the Users that have logged in from all the configured Security Realm across that Jenkins instance. -
The list of internal Jenkins Users under
$JENKINS_HOME/users
are completely independent of the Users hosted on the IDP side. This means that if some properties from "User A" have been changed on the IDP side but that "User A" has not logged in to Jenkins since those updates in the properties, they won’t appear as updated under$JENKINS_HOME/users
(once the User logs in to Jenkins after the changes in the IDP, the information will be updated in the corresponding directory of the "User A" under$JENKINS_HOME/users
).
To illustrate those complex concepts, let’s take a look at the following example:
-
First, let’s assume that you have configured as Security Realm an Active Directory server and you have on the IDP side a User called "User A" that has never logged in to Jenkins. If you navigate under
$JENKINS_HOME/users
you won’t see any directory related to that "User A". -
Then, after logging in for the first time with "User A", you will see under
$JENKINS_HOME/users
a newly generated directory called$USER_A_ID_$RANDOMLY_AUTOGENERATED_HASH
. -
Let’s imagine the "User A" email is "userA@example.com", but due to an internal new requirement, now the email has changed on the IDP side to "user_A@example.com". If you don’t log in to Jenkins with the "User A" after the change in the IDP side occurred, the email that appears in the
config.xml
file under$JENKINS_HOME/users/$USER_A_ID_$RANDOMLY_AUTOGENERATED_HASH
will still be "userA@example.com". However, after you log in again with "User A", the change will be reflected in the aforementionedconfig.xml
and now the email will appear as "user_A@example.com". -
As mentioned before, the directory
$JENKINS_HOME/users
results in the combination of all the Users that have logged in from all the configured Security Realm. Following the example, let’s now imagine we change the Security Realm from Active Directory to LDAP and "User A" doesn’t exist on the new LDAP server, but "User B" does. Under the directory$JENKINS_HOME/users
will continue to exist the directory$JENKINS_HOME/users/$USER_A_ID_$RANDOMLY_AUTOGENERATED_HASH
(until manual deletion) and a directory for the "User B" won’t be populated until that "User B" logs in for the first time on Jenkins. This is the same concept that applies to migrating the Security Realm and preserving the Jenkins Users as explained in: Can I migrate my IDP and preserve the same users on Jenkins®?
Workaround
Is worth noting that there is no such built-in feature on Jenkins as a Service Account, that’s why this section is marked as a Workaround
instead of as a Resolution
.
Furthermore, not all the concepts explained in the Notes aside
are necessary to configure the Service Account as indicated below, they are introduced here for a better understanding from a holistic point of view of how the Jenkins Users are handled internally.
Here are the required steps to create a Service Account on Jenkins using a User from your IDP:
-
Create a mock user on your IDP side and grant it login capability.
-
Configure the user in Jenkins with the Roles you require in your RBAC setup.
-
Create an API Token for the user and store it securely.
-
Remove the login capabilities from the user on your IDP, for example, by changing the password to a randomized string so no one knows it. By the way, deleting the user completely from the IDP server won’t work because that will cause the API Tokens to fail.
-
The generated user won’t be able to log in to Jenkins, but the API Token is still valid to perform automated tasks.