5

On occasion I need to email all Jenkins users, for example warning them Jenkins will be offline for maintenance. The script below gives me email addresses for all people that Jenkins knows about, but it includes people that don’t have accounts, these are people that have committed changes that triggered builds. I’d like to remove them from the email list, that is the list should only include the users that you’d see on the securityRealm page. I’m looking for help modifying the script. Thanks.

import hudson.model.User
import hudson.tasks.Mailer

def users = User.getAll()
for (User u : users) {
    def mailAddress = u.getProperty(Mailer.UserProperty.class).getAddress()
    print(mailAddress + "; ")
}
khagler
  • 3,996
  • 29
  • 40
Marc Tompkins
  • 73
  • 1
  • 7

1 Answers1

7

First of all you should know that Jenkins will not always be able to tell you whether the user exists or not. From Jenkins' javadoc:

This happens, for example, when the security realm is on top of the servlet implementation, there's no way of even knowing if an user of a given name exists or not.

I found two solutions.

Solution 1

HudsonPrivateSecurityRealm.html#getAllUsers() returns all users who can login to the system. And this works for me:

import hudson.model.User
import hudson.tasks.Mailer
import jenkins.model.Jenkins

def realm = Jenkins.getInstance().getSecurityRealm()
def users = realm.getAllUsers()
for (User u : users) {
    def mailAddress = u.getProperty(Mailer.UserProperty.class).getAddress()
    print(mailAddress + "; ")
}

Note: this depends on the Jenkins config and may not work on the system where used another (not a HudsonPrivateSecurityRealm) security realm.

Solution 2

SecurityRealm#loadUserByUsername returns user details if user exists and throws UsernameNotFoundException otherwise:

import hudson.model.User
import hudson.tasks.Mailer
import jenkins.model.Jenkins
import org.acegisecurity.userdetails.UsernameNotFoundException

def realm = Jenkins.getInstance().getSecurityRealm()
def users = User.getAll()
for (User u : users) {
    try {
        realm.loadUserByUsername(u.getId()) // throws UsernameNotFoundException
        def mailAddress = u.getProperty(Mailer.UserProperty.class).getAddress()
        print(mailAddress + "; ")
    } catch (UsernameNotFoundException e) { }
 }

This is tricky one, but should work with all security realms as we use the method that exists in top level abstract class (SecurityRealm).

Vitalii Elenhaupt
  • 7,146
  • 3
  • 27
  • 43
  • I tried solution 1 and it worked, it also produced the list almost instantly, where as my solution takes about a minute. Thanks Vitalii! – Marc Tompkins Jun 22 '15 at 17:43
  • Thank you for some solutions. For the sake of reporting our results, I found that Solution 1 will not work with the Active Directory Plugin used for auth (that plugin does not have getAllUsers()). Solution 2 eventually times out our Apache httpd reverse proxy in front of Jenkins as I believe it is enumerating every user in AD (many thousands in our company). I suppose this is the sort of case solved by a product keeping its own user database, caching from AD/LDAP. – jblaine Apr 06 '17 at 15:48
  • @jblaine thank you for reporting this. What is the problem you are trying to solve ? I don't think you want to mail thousands of people at once... – Vitalii Elenhaupt Apr 06 '17 at 17:19
  • @VitaliiElenhaupt Hi there. We use AD for authentication and the Role Strategy Plugin for authorization. The builtin role "anonymous" has no privileges. The builtin role "authenticated" has very minimal privileges. So anyone in our company can login to our Jenkins server but effectively do nothing much of use until they've had us a) create a Jenkins folder for them and b) define a Role + set allowable permissions for that role. Once that has happened, we consider the person a "user". So in our case, I'm going to have to figure out some code to query "people with a role assigned". – jblaine Apr 21 '17 at 13:59