Commit 72327054 authored by Adrian Damian's avatar Adrian Damian
Browse files

Made user fname and lname available in GMS

parent 884b0d11
Loading
Loading
Loading
Loading
+2 −11
Original line number Diff line number Diff line
@@ -102,20 +102,11 @@ import com.unboundid.ldap.sdk.SearchResult;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.unboundid.ldap.sdk.SearchScope;
import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl;
import java.util.logging.Level;

public class LdapGroupDAO<T extends Principal> extends LdapDAO
{
    private static final Logger logger = Logger.getLogger(LdapGroupDAO.class);

    private static final String ACTUAL_GROUP_TOKEN = "<ACTUAL_GROUP>";
    private static final String GROUP_READ_ACI = "(targetattr = \"*\") " + 
            "(version 3.0;acl \"Group Read\";allow (read,compare,search)" + 
            "(groupdn = \"ldap:///<ACTUAL_GROUP>\");)";
    private static final String GROUP_WRITE_ACI = "(targetattr = \"*\") " + 
            "(version 3.0;acl \"Group Write\";allow " + 
            "(read,compare,search,selfwrite,write,add)" + 
            "(groupdn = \"ldap:///<ACTUAL_GROUP>\");)";
    
    private LdapUserDAO<T> userPersist;

@@ -282,7 +273,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                            User<X500Principal> user;
                            try
                            {
                                user = userPersist.getMember(memberDN, false);
                                user = userPersist.getMember(memberDN);
                            }
                            catch (UserNotFoundException e)
                            {
+68 −59
Original line number Diff line number Diff line
@@ -68,12 +68,25 @@
 */
package ca.nrc.cadc.ac.server.ldap;

import java.security.AccessControlException;
import java.security.Principal;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import javax.security.auth.x500.X500Principal;

import org.apache.log4j.Logger;

import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.net.TransientException;

import com.unboundid.ldap.sdk.CompareRequest;
import com.unboundid.ldap.sdk.CompareResult;
import com.unboundid.ldap.sdk.DN;
@@ -82,30 +95,39 @@ import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.SearchRequest;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.unboundid.ldap.sdk.SearchScope;
import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl;
import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl;
import java.security.AccessControlException;
import java.security.Principal;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.security.auth.x500.X500Principal;
import org.apache.log4j.Logger;

public class LdapUserDAO<T extends Principal> extends LdapDAO
{
    private static final Logger logger = Logger.getLogger(LdapUserDAO.class);

    // Map of identity type to LDAP attribute
    private Map<Class<?>, String> attribType = new HashMap<Class<?>, String>();
    private Map<Class<?>, String> userLdapAttrib = new HashMap<Class<?>, String>();
    
    // User attributes returned to the GMS
    private static final String LDAP_FNAME = "givenname";
    private static final String LDAP_LNAME = "sn";
    //TODO to add the rest
    private String[] userAttribs = new String[]{LDAP_FNAME, LDAP_LNAME};
    private String[] memberAttribs = new String[]{LDAP_FNAME, LDAP_LNAME};

    public LdapUserDAO(LdapConfig config)
    {
        super(config);
        this.attribType.put(HttpPrincipal.class, "cn");
        this.attribType.put(X500Principal.class, "distinguishedname");
        this.attribType.put(NumericPrincipal.class, "entryid");
        this.userLdapAttrib.put(HttpPrincipal.class, "uid");
        this.userLdapAttrib.put(X500Principal.class, "distinguishedname");
        
        // add the id attributes to user and member attributes
        String[] princs = userLdapAttrib.values().toArray(new String[userLdapAttrib.values().size()]);
        String[] tmp = new String[userAttribs.length + princs.length];
        System.arraycopy(princs, 0, tmp, 0, princs.length);
        System.arraycopy(userAttribs, 0, tmp, princs.length, userAttribs.length);
        userAttribs = tmp;
        
        tmp = new String[memberAttribs.length + princs.length];
        System.arraycopy(princs, 0, tmp, 0, princs.length);
        System.arraycopy(memberAttribs, 0, tmp, princs.length, memberAttribs.length);
        memberAttribs = tmp;
    }

    /**
@@ -122,7 +144,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    public User<T> getUser(T userID)
        throws UserNotFoundException, TransientException, AccessControlException
    {
        String searchField = (String) attribType.get(userID.getClass());
        String searchField = (String) userLdapAttrib.get(userID.getClass());
        if (searchField == null)
        {
            throw new IllegalArgumentException(
@@ -135,8 +157,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
        try
        {
            SearchRequest searchRequest = new SearchRequest(config.getUsersDN(), 
                    SearchScope.SUB, searchField, 
                    new String[] {"cn", "entryid", "entrydn", "dn"});
                    SearchScope.SUB, searchField, userAttribs);
 
            searchRequest.addControl(
                    new ProxiedAuthorizationV2RequestControl("dn:" + 
@@ -157,12 +178,13 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
        }
        User<T> user = new User<T>(userID);
        user.getIdentities().add(
                new HttpPrincipal(searchResult.getAttributeValue("cn")));

        user.getIdentities().add(
                new NumericPrincipal(
                        searchResult.getAttributeValueAsInteger("entryid")));
                new HttpPrincipal(searchResult.getAttributeValue(userLdapAttrib
                        .get(HttpPrincipal.class))));
        
        String fname = searchResult.getAttributeValue(LDAP_FNAME);
        String lname = searchResult.getAttributeValue(LDAP_LNAME);
        user.details.add(new PersonalDetails(fname, lname));
        //TODO populate user with the other returned personal or posix attributes
        return user;
    }   

@@ -182,14 +204,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    {
        try
        {
            String searchField = (String) attribType.get(userID.getClass());
            String searchField = (String) userLdapAttrib.get(userID.getClass());
            if (searchField == null)
            {
                throw new IllegalArgumentException(
                        "Unsupported principal type " + userID.getClass());
            }

            User user = getUser(userID);
            User<T> user = getUser(userID);
            Filter filter = Filter.createANDFilter(
                        Filter.createEqualityFilter(searchField, 
                                                    user.getUserID().getName()),
@@ -256,14 +278,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    {
        try
        {
            String searchField = (String) attribType.get(userID.getClass());
            String searchField = (String) userLdapAttrib.get(userID.getClass());
            if (searchField == null)
            {
                throw new IllegalArgumentException(
                        "Unsupported principal type " + userID.getClass());
            }

            User user = getUser(userID);
            User<T> user = getUser(userID);
            Filter filter = Filter.createANDFilter(
                        Filter.createEqualityFilter(searchField, 
                                                    user.getUserID().getName()),
@@ -301,14 +323,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    {
        try
        {
            String searchField = (String) attribType.get(userID.getClass());
            String searchField = (String) userLdapAttrib.get(userID.getClass());
            if (searchField == null)
            {
                throw new IllegalArgumentException(
                        "Unsupported principal type " + userID.getClass());
            }

            User user = getUser(userID);
            User<T> user = getUser(userID);
            DN userDN = getUserDN(user);

            CompareRequest compareRequest = 
@@ -333,16 +355,16 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    }
    
    /**
     * Returns a member user identified by the X500Principal only.
     * Returns a member user identified by the X500Principal only. The
     * returned object has the fields required by the GMS.
     * Note that this method binds as a proxy user and not as the 
     * subject.
     * @param userDN
     * @param bindAsSubject - true if Ldap commands executed as subject 
     * (proxy authorization) or false if they are executed as the user
     * in the connection.
     * @return
     * @throws UserNotFoundException
     * @throws LDAPException
     */
    User<X500Principal> getMember(DN userDN, boolean bindAsSubject)
    User<X500Principal> getMember(DN userDN)
        throws UserNotFoundException, LDAPException
    {
        Filter filter = 
@@ -351,50 +373,37 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
        
        SearchRequest searchRequest = 
                new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, 
                                  filter, 
                                  (String[]) this.attribType.values().toArray(
                                  new String[this.attribType.values().size()]));
        
        if (bindAsSubject)
        {
        	searchRequest.addControl(
        				new ProxiedAuthorizationV2RequestControl("dn:" + 
        						getSubjectDN().toNormalizedString()));
        }
                                  filter, memberAttribs);
        
        SearchResultEntry searchResult = 
                getConnection().searchForEntry(searchRequest);

        if (searchResult == null)
        {
            String msg = "User not found " + userDN;
            String msg = "Member not found " + userDN;
            logger.debug(msg);
            throw new UserNotFoundException(msg);
        }
        User<X500Principal> user = new User<X500Principal>(
                new X500Principal(searchResult.getAttributeValue(
                        (String) attribType.get(X500Principal.class))));

                        (String) userLdapAttrib.get(X500Principal.class))));
        String princ = searchResult.getAttributeValue(
                (String) userLdapAttrib.get(HttpPrincipal.class));
        if (princ != null)
        {
            user.getIdentities().add(new HttpPrincipal(princ));
        }
        String fname = searchResult.getAttributeValue(LDAP_FNAME);
        String lname = searchResult.getAttributeValue(LDAP_LNAME);
        user.details.add(new PersonalDetails(fname, lname));
        return user;
    }
    
    /**
     * Returns a member user identified by the X500Principal only.
     * @param userDN
     * @return
     * @throws UserNotFoundException
     * @throws LDAPException
     */
    User<X500Principal> getMember(DN userDN)
        throws UserNotFoundException, LDAPException
    {
        return getMember(userDN, true);
    }

    DN getUserDN(User<? extends Principal> user)
        throws LDAPException, UserNotFoundException
    {
        String searchField = (String) attribType.get(user.getUserID().getClass());
        String searchField = (String) userLdapAttrib.get(user.getUserID().getClass());
        if (searchField == null)
        {
            throw new IllegalArgumentException(
+114 −11
Original line number Diff line number Diff line
@@ -68,22 +68,33 @@
 */
package ca.nrc.cadc.ac.server.ldap;

import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.util.Log4jInit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;

import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserDetails;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.util.Log4jInit;

import com.unboundid.ldap.sdk.DN;

/**
 *
 * @author jburke
@@ -102,7 +113,9 @@ public class LdapUserDAOTest
//    static String userBaseDN = "ou=Users,ou=ds,dc=canfar,dc=net";
//    static String groupBaseDN = "ou=Groups,ou=ds,dc=canfar,dc=net";
    
    static final String testUserDN = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca";
    static final String testUserX509DN = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca";
    static final String testUserDN = "uid=cadcdaotest1," + usersDN;
    
    
    static User<X500Principal> testUser;
    static LdapConfig config;
@@ -113,9 +126,12 @@ public class LdapUserDAOTest
    {
        Log4jInit.setLevel("ca.nrc.cadc.ac", Level.DEBUG);
        
        testUser = new User<X500Principal>(new X500Principal(testUserDN));
        testUser = new User<X500Principal>(new X500Principal(testUserX509DN));
    
        config = new LdapConfig(server, port, adminDN, adminPW, usersDN, groupsDN, adminGroupsDN);
        
        testUser.details.add(new PersonalDetails("CADC", "DAOTest1"));
        testUser.getIdentities().add(new HttpPrincipal("CadcDaoTest1"));        
    }

    LdapUserDAO<X500Principal> getUserDAO()
@@ -139,8 +155,8 @@ public class LdapUserDAOTest
            {
                try
                {
                    User actual = getUserDAO().getUser(testUser.getUserID());
                    assertEquals(testUser, actual);
                    User<X500Principal> actual = getUserDAO().getUser(testUser.getUserID());
                    check(testUser, actual);
                    
                    return null;
                }
@@ -150,6 +166,7 @@ public class LdapUserDAOTest
                }
            }
        });

    }

    /**
@@ -217,4 +234,90 @@ public class LdapUserDAOTest
        });
    }
    
    
    /**
     * Test of getMember.
     */
    @Test
    public void testGetMember() throws Exception
    {
        Subject subject = new Subject();
        subject.getPrincipals().add(testUser.getUserID());

        // do everything as owner
        Subject.doAs(subject, new PrivilegedExceptionAction<Object>()
        {
            public Object run() throws Exception
            {
                try
                {   
                    User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN));
                    check(testUser, actual);
                    return null;
                }
                catch (Exception e)
                {
                    throw new Exception("Problems", e);
                }
            }
        });
        
        
        // should also work as a different user
        subject = new Subject();
        subject.getPrincipals().add(new HttpPrincipal("CadcDaoTest2"));

        // do everything as owner
        Subject.doAs(subject, new PrivilegedExceptionAction<Object>()
        {
            public Object run() throws Exception
            {
                try
                {   
                    User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN));
                    check(testUser, actual);
                    return null;
                }
                catch (Exception e)
                {
                    throw new Exception("Problems", e);
                }
            }
        });
    }
    
    
    private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2)
    {
        assertEquals(user1, user2);
        assertEquals(user1.details, user2.details);
        assertEquals(user1.details.size(), user2.details.size());
        assertEquals(user1.getIdentities(), user2.getIdentities());
        for(UserDetails d1 : user1.details)
        {
            assertTrue(user2.details.contains(d1));
            if(d1 instanceof PersonalDetails)
            {
                PersonalDetails pd1 = (PersonalDetails)d1;
                boolean found = false;
                for(UserDetails d2 : user2.details)
                {
                    if(d2 instanceof PersonalDetails)
                    {
                        PersonalDetails pd2 = (PersonalDetails)d2;
                        assertEquals(pd1, pd2); // already done in contains above but just in case
                        assertEquals(pd1.address, pd2.address);
                        assertEquals(pd1.city, pd2.city);
                        assertEquals(pd1.country, pd2.country);
                        assertEquals(pd1.email, pd2.email);
                        assertEquals(pd1.institute, pd2.institute);
                        found = true;
                    }
                    assertTrue(found);
                }
            }
        }
        
    }
    
}