The first time I run into the issue
"Not sending mail to unregistered user abc@xyz.com because your SCM claimed this was associated with a user ID `` which your security realm does not recognize; you may need changes in your SCM plugin."
(see https://docs.cloudbees.com/docs/cloudbees-ci-kb/latest/client-and-managed-masters/not-sending-mail-to-unregistered-user-associated-with-scm)
was all developers had to change their email address to a new domain.
Even after telling them to update the email address in their Jenkins account, it did not really fix the issue for all developers.
After checking the source code https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java
and doing some tests according to the source code, I came to the following results:
Jenkins always creates new Jenkins user accounts nevertheless if "Create new accounts based on author/committer's email?" is checked:
https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L468
user = getUser(csAuthorEmail, true);
}
if (user != null && setUserDetails) {
user.setFullName(csAuthor);
... or not checked:
https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L502
user = getUser(emailParts[0], true);
Use case A:
At the beginning the Jenkins server was running with "Create new accounts based on author/committer's email?" false.
The result is that some developers have got 2 Jenkins accounts now:
UserID 1: "firstname.lastname" (auto-created account by GitChangeSet)
UserID 2: "lastname" ("lastname" is in my company the user name for the Jenkins login and matches the LDAP account and is dependent on your company's policy)
I guess this happens when a developer logs into Jenkins after pushing his/her first commit.
Use case B:
Later all developers have updated their email address for UserID 2, but not in UserID 1. Which fixed the issue for some developers,
but not for all because:
https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L488
user = getUser(csAuthor, false);
is looking for the ID or FullName of all Jenkins accounts that matches the extracted "user.name" of the author commit
(e.g. "Firstname LASTNAME <firstname.lastname@mycompany.com>" -> "user.name" = "Firstname LASTNAME").
and this comparison is case sensitive!
One little typo and the account "does not exist" although it exists and then a new account will be created with "firstname.lastname" (as ID and Full Name)!
You can test it via "Script Console" in Jenkins, e.g. like this:
def u = User.get('lastname', false, Collections.emptyMap()) return "id = " + u.getId() + ", FullName = " + u.getFullName() + ", no. of authorities = " + u.getAuthorities()?.size()
Lets assume there is a little typo between Jenkins account FullName and author commit
(which is a quite common practice in developers life because "git config user.name" is not always set correctly for all dev-tools and environments) then this line will be used:
https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L499
String[] emailParts = csAuthorEmail.split("@");
if (emailParts.length > 0) {
try {
user = getUser(emailParts[0], true);
And this is for my company (LDAP policy) always the UN-authorized Jenkins User Account!
Improvement B.1)
In my opinion to improve here the functionality of enabling/disabling "auto-create user account" should be implemented.
From a security point of view this ends up in the same situation:
no account -> no email will be send
no authorized account -> no email will be send
Improvement B.2)
Another improvement could be that
user = getUser(csAuthor, false);
is looking for matching Full Names but with case-insensitivity.
Improvement B.3)
Another improvement could be (if auto-creating is enabled):
user = getUser(emailParts[0], false);
user = getUser(emailParts[0], true);
user.setFullName(csAuthor);
setMail(user, csAuthorEmail);
OR in respect of this ticket here instead of creating "firstname.lastname" let's take the extracted author name:
user = getUser(csAuthor, true);
setMail(user, csAuthorEmail);
Improvement B.4)
If
"Create new accounts based on author/committer's email?" false
"Use existing account with same email if found?" true
then before Improvement suggestion B.3 search for accounts with the same email address.
The code here https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L458 and ff. can be re-used.
Use case C:
Later my company changed the LDAP policy (1-to-n characters of the firstname plus lastname) and now things got really bad.
So I changed the Jenkins server setting to:
"Create new accounts based on author/committer's email?" true
"Use existing account with same email if found?" true
because I read it might fix the issue. But in real life for some developers it doesn't work either.
And the reason is there is a loop in the source code:
https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java#L459
for(User existingUser : User.getAll()) {
if (csAuthorEmail.equalsIgnoreCase(getMail(existingUser))) {
user = existingUser;
setUserDetails = false;
break; }
}
and it stops searching as soon as it got the first UserID with the matching email address.
In real life some developers have got 3
Jenkins accounts now:
user.name = "Firstname LASTNAME"
user.email = "firstname.lastname@mycompany.com"
author commit = "Firstname LASTNAME <firstname.lastname@mycompany.com>"
LDAP/AD = "lastname"
UserID 1: "firstname.lastname" (from use case A or use case B)
UserID 2: "firstname.lastname@mycompany.com" (from use case B)
UserID 3: "lastname" (authorized by LDAP)
Well, UserID 1 and 2 are both smaller than UserID 3 ("firstname.lastname" < ""firstname.lastname@mycompany.com"" < "lastname")
and that's why for some users the UN-authorized UserID 1 or 2 are always taken and not the authorized account UserID 3.
You can test it via "Script Console" in Jenkins, e.g. like this:
def u = []
for (User existingUser : User.getAll()) {
if ('firstname.lastname@mycompany.com'.equalsIgnoreCase(existingUser.getProperty(hudson.tasks.Mailer.UserProperty.class).getExplicitlyConfiguredAddress())) {
u += existingUser.getId() + " : " + existingUser.getFullName() + " (" + existingUser.getAuthorities().size() + ")"
}
}
return u
Improvement C.1)
So a quick bug fix (see line 460) could look like this:
for(User existingUser : User.getAll()) {
if (csAuthorEmail.equalsIgnoreCase(getMail(existingUser)) && existingUser.getAuthorities().size() > 0) { user = existingUser;
setUserDetails = false;
break;
}
}
Summary:
As long as the source code is not improved and you don't want to check "Allow sending to unregistered users" then the only workaround is:
Either my company adapts the LDAP policy to the Jenkins logic:
firstname.lastname@mycompany.com
or
firstname.lastname
OR
to disable "Create new accounts based on author/committer's email?" and tell a developers:
log into Jenkins and make sure that:
git user.name = jenkins.fullname (CASE-SENSITIVE!)
git user.email = jenkins.email
Can't the e-mail address(es) in the commit message be used to find Jenkins security realm users?
The e-mail address in my commit messages is the same as the e-mail address associated with my Jenkins account. Why can those not be matched up?