Skip to content

Commit

Permalink
[JENKINS-6648] Look up e-mail address from AD.
Browse files Browse the repository at this point in the history
  • Loading branch information
kohsuke committed Nov 4, 2011
1 parent 5598fd2 commit 5c1a366
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 25 deletions.
@@ -1,17 +1,14 @@
package hudson.plugins.active_directory;

import com4j.COM4J;
import com4j.Com4jObject;
import com4j.ComException;
import com4j.Variant;
import com4j.typelibs.activeDirectory.IADs;
import com4j.typelibs.activeDirectory.IADsGroup;
import com4j.typelibs.activeDirectory.IADsOpenDSObject;
import com4j.typelibs.activeDirectory.IADsUser;
import com4j.typelibs.ado20.ClassFactory;
import com4j.typelibs.ado20._Command;
import com4j.typelibs.ado20._Connection;
import com4j.typelibs.ado20._Recordset;
import hudson.security.GroupDetails;
import hudson.security.SecurityRealm;
import hudson.tasks.MailAddressResolver;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.GrantedAuthority;
Expand All @@ -24,12 +21,18 @@
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataAccessException;

import hudson.security.GroupDetails;
import hudson.security.SecurityRealm;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import com4j.COM4J;
import com4j.Com4jObject;
import com4j.ComException;
import com4j.Variant;
import com4j.typelibs.activeDirectory.IADs;
import com4j.typelibs.activeDirectory.IADsGroup;
import com4j.typelibs.activeDirectory.IADsOpenDSObject;
import com4j.typelibs.activeDirectory.IADsUser;
import com4j.typelibs.ado20.ClassFactory;
import com4j.typelibs.ado20._Command;
import com4j.typelibs.ado20._Connection;
import com4j.typelibs.ado20._Recordset;

/**
* {@link AuthenticationProvider} with Active Directory, plus {@link UserDetailsService}
Expand Down Expand Up @@ -105,7 +108,8 @@ protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticati
username, password,
!isAccountDisabled(usr),
true, true, true,
groups.toArray(new GrantedAuthority[groups.size()])
groups.toArray(new GrantedAuthority[groups.size()]),
usr.firstName(), usr.lastName(), usr.emailAddress(), usr.telephoneNumber().toString()
);
}

Expand Down
@@ -0,0 +1,47 @@
package hudson.plugins.active_directory;

import hudson.Extension;
import hudson.model.Hudson;
import hudson.model.User;
import hudson.security.SecurityRealm;
import hudson.tasks.MailAddressResolver;
import org.acegisecurity.AcegiSecurityException;
import org.springframework.dao.DataAccessException;

import java.util.logging.Logger;

import static java.util.logging.Level.*;

/**
* If the security realm is Active Directory, try to pick up e-mail
* address from it.
*
* @author Animesh Banerjee
*
*/
@Extension
public class ActiveDirectoryMailAddressResolverImpl extends
MailAddressResolver {
public String findMailAddressFor(User u) {
SecurityRealm realm = Hudson.getInstance().getSecurityRealm();
if(!(realm instanceof ActiveDirectorySecurityRealm)){
return null;
}
try {
ActiveDirectoryUserDetail details = (ActiveDirectoryUserDetail) realm
.getSecurityComponents().userDetails.loadUserByUsername(u
.getId());
LOGGER.log(FINE, "Email address = '"+ details.getMail() + "'");
return details.getMail();
} catch (DataAccessException e) {
LOGGER.log(FINE, "Failed to look Active Directory for e-mail address", e);
return null;
} catch (AcegiSecurityException e) {
LOGGER.log(FINE, "Failed to look up Active Directory for e-mail address", e);
return null;
}
}

private static final Logger LOGGER = Logger
.getLogger(ActiveDirectoryMailAddressResolverImpl.class.getName());
}
Expand Up @@ -178,13 +178,26 @@ public UserDetails retrieveUser(String username, String password, String domainN

context.close();

return new ActiveDirectoryUserDetail(id, password, true, true, true, true, groups.toArray(new GrantedAuthority[groups.size()]));
return new ActiveDirectoryUserDetail(id, password, true, true, true, true, groups.toArray(new GrantedAuthority[groups.size()]),
getStringAttribute(user, "givenName"),
getStringAttribute(user, "sn"),
getStringAttribute(user, "mail"),
getStringAttribute(user, "telephoneNumber")
);
} catch (NamingException e) {
LOGGER.log(Level.WARNING, "Failed to retrieve user information for "+username, e);
throw new BadCredentialsException("Failed to retrieve user information for "+username, e);
}
}

private String getStringAttribute(Attributes user, String name) throws NamingException {
Attribute a = user.get(name);
if (a==null) return null;
Object v = a.get();
if (v==null) return null;
return v.toString();
}

/**
* Returns the full user principal name of the form "joe@europe.contoso.com".
*
Expand Down
@@ -1,15 +1,58 @@
package hudson.plugins.active_directory;

import java.util.HashMap;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.User;

/**
* @author Kohsuke Kawaguchi
*/
public class ActiveDirectoryUserDetail extends User {
public ActiveDirectoryUserDetail(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException {
// Acegi doesn't like null password, but during remember-me processing we don't know the password.
// so we need to set some dummy. See #1229
super(username, password!=null?password:"PASSWORD", enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
// additional attributes from Active Directory
private final String givenName, sn, mail, telephoneNumber;

public ActiveDirectoryUserDetail(String username, String password,
boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
GrantedAuthority[] authorities,
String givenName, String sn, String mail, String telephoneNumber)
throws IllegalArgumentException {
// Acegi doesn't like null password, but during remember-me processing
// we don't know the password so we need to set some dummy. See #1229
super(username, password != null ? password : "PASSWORD", enabled,
accountNonExpired, credentialsNonExpired, accountNonLocked,
authorities);

this.givenName = givenName;
this.sn = sn;
this.mail = mail;
this.telephoneNumber = telephoneNumber;
}

public String getGivenName() {
return givenName;
}
}

/**
* Surname, AKA last name.
* LDAP "sn" attribute.
*/
public String getLastName() {
return sn;
}

public String getMail() {
return mail;
}

public String getTelephoneNumber() {
return telephoneNumber;
}

public static long getSerialVersionUID() {
return serialVersionUID;
}

private static final long serialVersionUID = 1L;
}

0 comments on commit 5c1a366

Please sign in to comment.