Loading projects/cadcAccessControl-Server/build.xml +3 −4 Original line number Diff line number Diff line Loading @@ -141,11 +141,10 @@ <pathelement path="${build}/test/class"/> <pathelement path="${testingJars}"/> </classpath> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTest" />--> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTestImpl" />--> <test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTest" /> <test name="ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest" /> <!--<test name="ca.nrc.cadc.ac.server.web.GroupActionFactoryTest" />--> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapUserDAOTest" />--> <test name="ca.nrc.cadc.ac.server.web.GroupActionFactoryTest" /> <test name="ca.nrc.cadc.ac.server.ldap.LdapUserDAOTest" /> <formatter type="plain" usefile="false" /> </junit> </target> Loading projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java +2 −24 Original line number Diff line number Diff line Loading @@ -86,11 +86,9 @@ public class LdapConfig public static final String LDAP_PASSWD = "passwd"; public static final String LDAP_USERS_DN = "usersDn"; public static final String LDAP_GROUPS_DN = "groupsDn"; public static final String LDAP_DELETED_GROUPS_DN = "deletedGroupsDn"; private String usersDN; private String groupsDN; private String deletedGroupsDN; private String server; private int port; private String adminUserDN; Loading Loading @@ -159,21 +157,12 @@ public class LdapConfig LDAP_GROUPS_DN); } String ldapDeletedGroupsDn = config.getProperty(LDAP_DELETED_GROUPS_DN); if (!StringUtil.hasText(ldapDeletedGroupsDn)) { throw new RuntimeException("failed to read property " + LDAP_DELETED_GROUPS_DN); } return new LdapConfig(server, Integer.valueOf(port), ldapAdmin, ldapPasswd, ldapUsersDn, ldapGroupsDn, ldapDeletedGroupsDn); ldapPasswd, ldapUsersDn, ldapGroupsDn); } public LdapConfig(String server, int port, String adminUserDN, String adminPasswd, String usersDN, String groupsDN, String deletedGroupsDN) String adminPasswd, String usersDN, String groupsDN) { if (!StringUtil.hasText(server)) { Loading Loading @@ -205,11 +194,6 @@ public class LdapConfig throw new IllegalArgumentException("Illegal groups LDAP DN: " + groupsDN); } if (!StringUtil.hasText(deletedGroupsDN)) { throw new IllegalArgumentException("Illegal groups LDAP DN: " + deletedGroupsDN); } this.server = server; this.port = port; Loading @@ -217,7 +201,6 @@ public class LdapConfig this.adminPasswd = adminPasswd; this.usersDN = usersDN; this.groupsDN = groupsDN; this.deletedGroupsDN = deletedGroupsDN; } public String getUsersDN() Loading @@ -230,11 +213,6 @@ public class LdapConfig return this.groupsDN; } public String getDeletedGroupsDN() { return this.deletedGroupsDN; } public String getServer() { return this.server; Loading projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +172 −153 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.logging.Level; import javax.security.auth.x500.X500Principal; import org.apache.log4j.Logger; Loading Loading @@ -128,23 +129,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO this.userPersist = userPersist; } /** * Get the group with the given Group ID. * * @param groupID The Group unique ID. * * @return A Group instance * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ public Group getGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { return getGroup(groupID, true); } /** * Creates the group. * Loading @@ -161,6 +145,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO throws GroupAlreadyExistsException, TransientException, UserNotFoundException, AccessControlException { if (group.getOwner() == null) { throw new IllegalArgumentException("Group owner must be specified"); } try { getGroup(group.getID()); Loading @@ -180,7 +169,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO { throw new AccessControlException( "Unable to activate group " + group.getID() + " because " + group.getOwner().getUserID().getName() " because " + getSubjectDN().toString() + " is not the owner"); } Loading @@ -189,10 +178,23 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO new Modification(ModificationType.DELETE, "nsaccountlock"); mods.add(mod); Group modifiedGroup = modifyGroup(group, inactiveGroup, mods); Group activatedGroup = modifyGroup(group, inactiveGroup, mods); return new ActivatedGroup(activatedGroup.getID(), activatedGroup.getOwner()); new ActivatedGroup(modifiedGroup.getID(), modifiedGroup.getOwner()); activatedGroup.description = modifiedGroup.description; activatedGroup.publicRead = modifiedGroup.publicRead; activatedGroup.groupRead = modifiedGroup.groupRead; activatedGroup.groupWrite = modifiedGroup.groupWrite; activatedGroup.getProperties() .addAll(modifiedGroup.getProperties()); activatedGroup.getGroupMembers() .addAll(modifiedGroup.getGroupMembers()); activatedGroup.getUserMembers() .addAll(modifiedGroup.getUserMembers()); return activatedGroup; } catch (GroupNotFoundException ignore) {} Loading Loading @@ -300,108 +302,20 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } /** * Deletes the group. * Get the group with the given Group ID. * * @param groupID The group to delete * @param groupID The Group unique ID. * * @return A Group instance * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ public void deleteGroup(String groupID) public Group getGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { Group group = getGroup(groupID); List<Modification> modifs = new ArrayList<Modification>(); modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); if (group.description != null) { modifs.add(new Modification(ModificationType.DELETE, "description")); } if (group.groupRead != null || group.groupWrite != null || group.publicRead) { modifs.add(new Modification(ModificationType.DELETE, "aci")); } if (!group.getGroupMembers().isEmpty() || !group.getUserMembers().isEmpty()) { modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); } ModifyRequest modifyRequest = new ModifyRequest(getGroupDN(group.getID()), modifs); try { modifyRequest.addControl( new ProxiedAuthorizationV2RequestControl( "dn:" + getSubjectDN().toNormalizedString())); LDAPResult result = getConnection().modify(modifyRequest); } catch (LDAPException e1) { throw new RuntimeException("LDAP problem", e1); } try { getGroup(group.getID()); throw new RuntimeException("BUG: group not deleted " + group.getID()); } catch (GroupNotFoundException ignore) {} } /** * Obtain a Collection of Groups that fit the given query. * * @param userID The userID. * @param role Role of the user, either owner, member, or read/write. * @param groupID The Group ID. * * @return Collection of Groups * matching GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN, * readGrDN.toNormalizedString()) the query, or empty * Collection. Never null. * @throws TransientException If an temporary, unexpected problem occurred. * @throws UserNotFoundException * @throws GroupNotFoundException */ public Collection<Group> searchGroups(T userID, Role role, String groupID) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { User<T> user = new User<T>(userID); DN userDN; try { userDN = userPersist.getUserDN(user); } catch (LDAPException e) { // TODO check which LDAP exceptions are transient and which // ones are // access control throw new TransientException("Error getting user", e); } if (role == Role.OWNER) { return getOwnerGroups(user, userDN, groupID); } else if (role == Role.MEMBER) { return getMemberGroups(user, userDN, groupID); } else if (role == Role.RW) { return getRWGroups(user, userDN, groupID); } throw new IllegalArgumentException("Unknown role " + role); return getGroup(groupID, true); } private Group getGroup(String groupID, boolean withMembers) Loading Loading @@ -462,17 +376,17 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO DN memberDN = new DN(member); if (memberDN.isDescendantOf(config.getUsersDN(), false)) { User<X500Principal> usr; User<X500Principal> user; try { usr = userPersist.getMember(memberDN); user = userPersist.getMember(memberDN); } catch (UserNotFoundException e) { throw new RuntimeException( "BUG: group member not found"); } ldapGroup.getUserMembers().add(usr); ldapGroup.getUserMembers().add(user); } else if (memberDN.isDescendantOf(config.getGroupsDN(), false)) Loading Loading @@ -582,7 +496,12 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO modifs.add(new Modification(ModificationType.DELETE, "description")); } else if (newGroup.description != null) else if (newGroup.description != null && oldGroup.description == null) { modifs.add(new Modification(ModificationType.ADD, "description", newGroup.description)); } else if (newGroup.description != null && oldGroup.description != null) { modifs.add(new Modification(ModificationType.REPLACE, "description", newGroup.description)); Loading Loading @@ -705,54 +624,113 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } catch (GroupNotFoundException e) { throw new RuntimeException("BUG: new group not found"); throw new RuntimeException("BUG: modified group not found"); } } /** * Returns a group based on its LDAP DN. The returned group is bared * (contains only group ID, owner and description). * Deletes the group. * * @param groupDN * @return * @throws com.unboundid.ldap.sdk.LDAPException * @throws ca.nrc.cadc.ac.GroupNotFoundException * @throws ca.nrc.cadc.ac.UserNotFoundException * @param groupID The group to delete * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ protected Group getGroup(DN groupDN) throws LDAPException, GroupNotFoundException, UserNotFoundException public void deleteGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { SearchResultEntry searchResult = getConnection().getEntry(groupDN.toNormalizedString(), new String[] {"cn", "description", "owner", "modifytimestamp"}); Group group = getGroup(groupID); List<Modification> modifs = new ArrayList<Modification>(); modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); if (searchResult == null) if (group.description != null) { String msg = "Group not found " + groupDN; logger.debug(msg); throw new GroupNotFoundException(groupDN.toNormalizedString()); modifs.add(new Modification(ModificationType.DELETE, "description")); } DN ownerDN = searchResult.getAttributeValueAsDN("owner"); User<X500Principal> owner = userPersist.getMember(ownerDN); Group group = new Group(searchResult.getAttributeValue("cn"), owner); group.description = searchResult.getAttributeValue("description"); group.lastModified = searchResult.getAttributeValueAsDate("modifytimestamp"); return group; if (group.groupRead != null || group.groupWrite != null || group.publicRead) { modifs.add(new Modification(ModificationType.DELETE, "aci")); } protected DN getGroupDN(String groupID) if (!group.getGroupMembers().isEmpty() || !group.getUserMembers().isEmpty()) { modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); } ModifyRequest modifyRequest = new ModifyRequest(getGroupDN(group.getID()), modifs); try { modifyRequest.addControl( new ProxiedAuthorizationV2RequestControl( "dn:" + getSubjectDN().toNormalizedString())); LDAPResult result = getConnection().modify(modifyRequest); } catch (LDAPException e1) { throw new RuntimeException("LDAP problem", e1); } try { return new DN("cn=" + groupID + "," + config.getGroupsDN()); getGroup(group.getID()); throw new RuntimeException("BUG: group not deleted " + group.getID()); } catch (GroupNotFoundException ignore) {} } /** * Obtain a Collection of Groups that fit the given query. * * @param userID The userID. * @param role Role of the user, either owner, member, or read/write. * @param groupID The Group ID. * * @return Collection of Groups * matching GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN, * readGrDN.toNormalizedString()) the query, or empty * Collection. Never null. * @throws TransientException If an temporary, unexpected problem occurred. * @throws UserNotFoundException * @throws GroupNotFoundException */ public Collection<Group> searchGroups(T userID, Role role, String groupID) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { User<T> user = new User<T>(userID); DN userDN; try { userDN = userPersist.getUserDN(user); } catch (LDAPException e) { // TODO check which LDAP exceptions are transient and which // ones are // access control throw new TransientException("Error getting user", e); } throw new IllegalArgumentException(groupID + " not a valid group ID"); if (role == Role.OWNER) { return getOwnerGroups(user, userDN, groupID); } else if (role == Role.MEMBER) { return getMemberGroups(user, userDN, groupID); } else if (role == Role.RW) { return getRWGroups(user, userDN, groupID); } throw new IllegalArgumentException("Unknown role " + role); } protected Collection<Group> getOwnerGroups(User<T> user, DN userDN, Loading Loading @@ -1020,7 +998,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO if (searchResult == null) { String msg = "Group not found " + groupID; String msg = "Inactive Group not found " + groupID; logger.debug(msg); throw new GroupNotFoundException(msg); } Loading @@ -1033,4 +1011,45 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO return new Group(groupCN, owner); } /** * Returns a group based on its LDAP DN. The returned group is bare * (contains only group ID, description, modifytimestamp). * * @param groupDN * @return * @throws com.unboundid.ldap.sdk.LDAPException * @throws ca.nrc.cadc.ac.GroupNotFoundException * @throws ca.nrc.cadc.ac.UserNotFoundException */ protected Group getGroup(DN groupDN) throws LDAPException, GroupNotFoundException, UserNotFoundException { SearchResultEntry searchResult = getConnection().getEntry(groupDN.toNormalizedString(), new String[] {"cn", "description"}); if (searchResult == null) { String msg = "Group not found " + groupDN; logger.debug(msg); throw new GroupNotFoundException(groupDN.toNormalizedString()); } Group group = new Group(searchResult.getAttributeValue("cn")); group.description = searchResult.getAttributeValue("description"); return group; } protected DN getGroupDN(String groupID) { try { return new DN("cn=" + groupID + "," + config.getGroupsDN()); } catch (LDAPException e) { } throw new IllegalArgumentException(groupID + " not a valid group ID"); } } projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +29 −11 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ 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; Loading Loading @@ -138,7 +139,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO new String[] {"cn", "entryid", "entrydn", "dn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); searchResult = getConnection().searchForEntry(searchRequest); } Loading Loading @@ -198,7 +200,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO filter, new String[] {"memberOf"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); Loading Loading @@ -271,7 +274,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO filter, new String[] {"cn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResults = getConnection().searchForEntry(searchRequest); Loading Loading @@ -312,7 +316,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO "memberOf", groupID); compareRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); CompareResult compareResult = getConnection().compare(compareRequest); Loading @@ -337,11 +342,23 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO User<X500Principal> getMember(DN userDN) throws UserNotFoundException, LDAPException { SearchResultEntry searchResult = getConnection().getEntry( userDN.toNormalizedString(), Filter filter = Filter.createEqualityFilter("entrydn", userDN.toNormalizedString()); SearchRequest searchRequest = new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, filter, (String[]) this.attribType.values().toArray( new String[this.attribType.values().size()])); searchRequest.addControl( new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); if (searchResult == null) { String msg = "User not found " + userDN; Loading Loading @@ -373,7 +390,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO searchField, new String[] {"entrydn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); Loading projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java +11 −9 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ package ca.nrc.cadc.ac.server.ldap; import static ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest.config; import static org.junit.Assert.assertTrue; import java.security.PrivilegedExceptionAction; Loading @@ -84,13 +85,14 @@ import com.unboundid.ldap.sdk.LDAPConnection; public class LdapDAOTest { LdapConfig config = new LdapConfig( "mach275.cadc.dao.nrc.ca", 389, "uid=webproxy,ou=administrators,ou=topologymanagement,o=netscaperoot", "go4it", "ou=Users,ou=ds,dc=canfar,dc=net", "ou=Groups,ou=ds,dc=canfar,dc=net", "ou=DeletedGroups,ou=ds,dc=canfar,dc=net"); static String server = "mach275.cadc.dao.nrc.ca"; static int port = 389; static String adminDN = "uid=webproxy,ou=administrators,ou=topologymanagement,o=netscaperoot"; static String adminPW = "go4it"; static String userBaseDN = "ou=Users,ou=ds,dc=canfartest,dc=net"; static String groupBaseDN = "ou=Groups,ou=ds,dc=canfartest,dc=net"; LdapConfig config = new LdapConfig(server, port, adminDN, adminPW, userBaseDN, groupBaseDN); @Test public void testLdapBindConnection() throws Exception Loading @@ -99,7 +101,7 @@ public class LdapDAOTest //LdapUserDAO<X500Principal> userDAO = new LdapUserDAO<X500Principal>(); // User authenticated with HttpPrincipal HttpPrincipal httpPrincipal = new HttpPrincipal("cadcauthtest2"); HttpPrincipal httpPrincipal = new HttpPrincipal("CadcDaoTest1"); Subject subject = new Subject(); subject.getPrincipals().add(httpPrincipal); Loading @@ -125,7 +127,7 @@ public class LdapDAOTest X500Principal subjPrincipal = new X500Principal( "cn=cadc authtest2 10635,ou=cadc,o=hia"); "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"); subject = new Subject(); subject.getPrincipals().add(subjPrincipal); Loading Loading
projects/cadcAccessControl-Server/build.xml +3 −4 Original line number Diff line number Diff line Loading @@ -141,11 +141,10 @@ <pathelement path="${build}/test/class"/> <pathelement path="${testingJars}"/> </classpath> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTest" />--> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTestImpl" />--> <test name="ca.nrc.cadc.ac.server.ldap.LdapDAOTest" /> <test name="ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest" /> <!--<test name="ca.nrc.cadc.ac.server.web.GroupActionFactoryTest" />--> <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapUserDAOTest" />--> <test name="ca.nrc.cadc.ac.server.web.GroupActionFactoryTest" /> <test name="ca.nrc.cadc.ac.server.ldap.LdapUserDAOTest" /> <formatter type="plain" usefile="false" /> </junit> </target> Loading
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java +2 −24 Original line number Diff line number Diff line Loading @@ -86,11 +86,9 @@ public class LdapConfig public static final String LDAP_PASSWD = "passwd"; public static final String LDAP_USERS_DN = "usersDn"; public static final String LDAP_GROUPS_DN = "groupsDn"; public static final String LDAP_DELETED_GROUPS_DN = "deletedGroupsDn"; private String usersDN; private String groupsDN; private String deletedGroupsDN; private String server; private int port; private String adminUserDN; Loading Loading @@ -159,21 +157,12 @@ public class LdapConfig LDAP_GROUPS_DN); } String ldapDeletedGroupsDn = config.getProperty(LDAP_DELETED_GROUPS_DN); if (!StringUtil.hasText(ldapDeletedGroupsDn)) { throw new RuntimeException("failed to read property " + LDAP_DELETED_GROUPS_DN); } return new LdapConfig(server, Integer.valueOf(port), ldapAdmin, ldapPasswd, ldapUsersDn, ldapGroupsDn, ldapDeletedGroupsDn); ldapPasswd, ldapUsersDn, ldapGroupsDn); } public LdapConfig(String server, int port, String adminUserDN, String adminPasswd, String usersDN, String groupsDN, String deletedGroupsDN) String adminPasswd, String usersDN, String groupsDN) { if (!StringUtil.hasText(server)) { Loading Loading @@ -205,11 +194,6 @@ public class LdapConfig throw new IllegalArgumentException("Illegal groups LDAP DN: " + groupsDN); } if (!StringUtil.hasText(deletedGroupsDN)) { throw new IllegalArgumentException("Illegal groups LDAP DN: " + deletedGroupsDN); } this.server = server; this.port = port; Loading @@ -217,7 +201,6 @@ public class LdapConfig this.adminPasswd = adminPasswd; this.usersDN = usersDN; this.groupsDN = groupsDN; this.deletedGroupsDN = deletedGroupsDN; } public String getUsersDN() Loading @@ -230,11 +213,6 @@ public class LdapConfig return this.groupsDN; } public String getDeletedGroupsDN() { return this.deletedGroupsDN; } public String getServer() { return this.server; Loading
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +172 −153 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.logging.Level; import javax.security.auth.x500.X500Principal; import org.apache.log4j.Logger; Loading Loading @@ -128,23 +129,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO this.userPersist = userPersist; } /** * Get the group with the given Group ID. * * @param groupID The Group unique ID. * * @return A Group instance * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ public Group getGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { return getGroup(groupID, true); } /** * Creates the group. * Loading @@ -161,6 +145,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO throws GroupAlreadyExistsException, TransientException, UserNotFoundException, AccessControlException { if (group.getOwner() == null) { throw new IllegalArgumentException("Group owner must be specified"); } try { getGroup(group.getID()); Loading @@ -180,7 +169,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO { throw new AccessControlException( "Unable to activate group " + group.getID() + " because " + group.getOwner().getUserID().getName() " because " + getSubjectDN().toString() + " is not the owner"); } Loading @@ -189,10 +178,23 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO new Modification(ModificationType.DELETE, "nsaccountlock"); mods.add(mod); Group modifiedGroup = modifyGroup(group, inactiveGroup, mods); Group activatedGroup = modifyGroup(group, inactiveGroup, mods); return new ActivatedGroup(activatedGroup.getID(), activatedGroup.getOwner()); new ActivatedGroup(modifiedGroup.getID(), modifiedGroup.getOwner()); activatedGroup.description = modifiedGroup.description; activatedGroup.publicRead = modifiedGroup.publicRead; activatedGroup.groupRead = modifiedGroup.groupRead; activatedGroup.groupWrite = modifiedGroup.groupWrite; activatedGroup.getProperties() .addAll(modifiedGroup.getProperties()); activatedGroup.getGroupMembers() .addAll(modifiedGroup.getGroupMembers()); activatedGroup.getUserMembers() .addAll(modifiedGroup.getUserMembers()); return activatedGroup; } catch (GroupNotFoundException ignore) {} Loading Loading @@ -300,108 +302,20 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } /** * Deletes the group. * Get the group with the given Group ID. * * @param groupID The group to delete * @param groupID The Group unique ID. * * @return A Group instance * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ public void deleteGroup(String groupID) public Group getGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { Group group = getGroup(groupID); List<Modification> modifs = new ArrayList<Modification>(); modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); if (group.description != null) { modifs.add(new Modification(ModificationType.DELETE, "description")); } if (group.groupRead != null || group.groupWrite != null || group.publicRead) { modifs.add(new Modification(ModificationType.DELETE, "aci")); } if (!group.getGroupMembers().isEmpty() || !group.getUserMembers().isEmpty()) { modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); } ModifyRequest modifyRequest = new ModifyRequest(getGroupDN(group.getID()), modifs); try { modifyRequest.addControl( new ProxiedAuthorizationV2RequestControl( "dn:" + getSubjectDN().toNormalizedString())); LDAPResult result = getConnection().modify(modifyRequest); } catch (LDAPException e1) { throw new RuntimeException("LDAP problem", e1); } try { getGroup(group.getID()); throw new RuntimeException("BUG: group not deleted " + group.getID()); } catch (GroupNotFoundException ignore) {} } /** * Obtain a Collection of Groups that fit the given query. * * @param userID The userID. * @param role Role of the user, either owner, member, or read/write. * @param groupID The Group ID. * * @return Collection of Groups * matching GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN, * readGrDN.toNormalizedString()) the query, or empty * Collection. Never null. * @throws TransientException If an temporary, unexpected problem occurred. * @throws UserNotFoundException * @throws GroupNotFoundException */ public Collection<Group> searchGroups(T userID, Role role, String groupID) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { User<T> user = new User<T>(userID); DN userDN; try { userDN = userPersist.getUserDN(user); } catch (LDAPException e) { // TODO check which LDAP exceptions are transient and which // ones are // access control throw new TransientException("Error getting user", e); } if (role == Role.OWNER) { return getOwnerGroups(user, userDN, groupID); } else if (role == Role.MEMBER) { return getMemberGroups(user, userDN, groupID); } else if (role == Role.RW) { return getRWGroups(user, userDN, groupID); } throw new IllegalArgumentException("Unknown role " + role); return getGroup(groupID, true); } private Group getGroup(String groupID, boolean withMembers) Loading Loading @@ -462,17 +376,17 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO DN memberDN = new DN(member); if (memberDN.isDescendantOf(config.getUsersDN(), false)) { User<X500Principal> usr; User<X500Principal> user; try { usr = userPersist.getMember(memberDN); user = userPersist.getMember(memberDN); } catch (UserNotFoundException e) { throw new RuntimeException( "BUG: group member not found"); } ldapGroup.getUserMembers().add(usr); ldapGroup.getUserMembers().add(user); } else if (memberDN.isDescendantOf(config.getGroupsDN(), false)) Loading Loading @@ -582,7 +496,12 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO modifs.add(new Modification(ModificationType.DELETE, "description")); } else if (newGroup.description != null) else if (newGroup.description != null && oldGroup.description == null) { modifs.add(new Modification(ModificationType.ADD, "description", newGroup.description)); } else if (newGroup.description != null && oldGroup.description != null) { modifs.add(new Modification(ModificationType.REPLACE, "description", newGroup.description)); Loading Loading @@ -705,54 +624,113 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } catch (GroupNotFoundException e) { throw new RuntimeException("BUG: new group not found"); throw new RuntimeException("BUG: modified group not found"); } } /** * Returns a group based on its LDAP DN. The returned group is bared * (contains only group ID, owner and description). * Deletes the group. * * @param groupDN * @return * @throws com.unboundid.ldap.sdk.LDAPException * @throws ca.nrc.cadc.ac.GroupNotFoundException * @throws ca.nrc.cadc.ac.UserNotFoundException * @param groupID The group to delete * * @throws GroupNotFoundException If the group was not found. * @throws TransientException If an temporary, unexpected problem occurred. */ protected Group getGroup(DN groupDN) throws LDAPException, GroupNotFoundException, UserNotFoundException public void deleteGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException { SearchResultEntry searchResult = getConnection().getEntry(groupDN.toNormalizedString(), new String[] {"cn", "description", "owner", "modifytimestamp"}); Group group = getGroup(groupID); List<Modification> modifs = new ArrayList<Modification>(); modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); if (searchResult == null) if (group.description != null) { String msg = "Group not found " + groupDN; logger.debug(msg); throw new GroupNotFoundException(groupDN.toNormalizedString()); modifs.add(new Modification(ModificationType.DELETE, "description")); } DN ownerDN = searchResult.getAttributeValueAsDN("owner"); User<X500Principal> owner = userPersist.getMember(ownerDN); Group group = new Group(searchResult.getAttributeValue("cn"), owner); group.description = searchResult.getAttributeValue("description"); group.lastModified = searchResult.getAttributeValueAsDate("modifytimestamp"); return group; if (group.groupRead != null || group.groupWrite != null || group.publicRead) { modifs.add(new Modification(ModificationType.DELETE, "aci")); } protected DN getGroupDN(String groupID) if (!group.getGroupMembers().isEmpty() || !group.getUserMembers().isEmpty()) { modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); } ModifyRequest modifyRequest = new ModifyRequest(getGroupDN(group.getID()), modifs); try { modifyRequest.addControl( new ProxiedAuthorizationV2RequestControl( "dn:" + getSubjectDN().toNormalizedString())); LDAPResult result = getConnection().modify(modifyRequest); } catch (LDAPException e1) { throw new RuntimeException("LDAP problem", e1); } try { return new DN("cn=" + groupID + "," + config.getGroupsDN()); getGroup(group.getID()); throw new RuntimeException("BUG: group not deleted " + group.getID()); } catch (GroupNotFoundException ignore) {} } /** * Obtain a Collection of Groups that fit the given query. * * @param userID The userID. * @param role Role of the user, either owner, member, or read/write. * @param groupID The Group ID. * * @return Collection of Groups * matching GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN, * readGrDN.toNormalizedString()) the query, or empty * Collection. Never null. * @throws TransientException If an temporary, unexpected problem occurred. * @throws UserNotFoundException * @throws GroupNotFoundException */ public Collection<Group> searchGroups(T userID, Role role, String groupID) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { User<T> user = new User<T>(userID); DN userDN; try { userDN = userPersist.getUserDN(user); } catch (LDAPException e) { // TODO check which LDAP exceptions are transient and which // ones are // access control throw new TransientException("Error getting user", e); } throw new IllegalArgumentException(groupID + " not a valid group ID"); if (role == Role.OWNER) { return getOwnerGroups(user, userDN, groupID); } else if (role == Role.MEMBER) { return getMemberGroups(user, userDN, groupID); } else if (role == Role.RW) { return getRWGroups(user, userDN, groupID); } throw new IllegalArgumentException("Unknown role " + role); } protected Collection<Group> getOwnerGroups(User<T> user, DN userDN, Loading Loading @@ -1020,7 +998,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO if (searchResult == null) { String msg = "Group not found " + groupID; String msg = "Inactive Group not found " + groupID; logger.debug(msg); throw new GroupNotFoundException(msg); } Loading @@ -1033,4 +1011,45 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO return new Group(groupCN, owner); } /** * Returns a group based on its LDAP DN. The returned group is bare * (contains only group ID, description, modifytimestamp). * * @param groupDN * @return * @throws com.unboundid.ldap.sdk.LDAPException * @throws ca.nrc.cadc.ac.GroupNotFoundException * @throws ca.nrc.cadc.ac.UserNotFoundException */ protected Group getGroup(DN groupDN) throws LDAPException, GroupNotFoundException, UserNotFoundException { SearchResultEntry searchResult = getConnection().getEntry(groupDN.toNormalizedString(), new String[] {"cn", "description"}); if (searchResult == null) { String msg = "Group not found " + groupDN; logger.debug(msg); throw new GroupNotFoundException(groupDN.toNormalizedString()); } Group group = new Group(searchResult.getAttributeValue("cn")); group.description = searchResult.getAttributeValue("description"); return group; } protected DN getGroupDN(String groupID) { try { return new DN("cn=" + groupID + "," + config.getGroupsDN()); } catch (LDAPException e) { } throw new IllegalArgumentException(groupID + " not a valid group ID"); } }
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +29 −11 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ 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; Loading Loading @@ -138,7 +139,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO new String[] {"cn", "entryid", "entrydn", "dn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); searchResult = getConnection().searchForEntry(searchRequest); } Loading Loading @@ -198,7 +200,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO filter, new String[] {"memberOf"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); Loading Loading @@ -271,7 +274,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO filter, new String[] {"cn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResults = getConnection().searchForEntry(searchRequest); Loading Loading @@ -312,7 +316,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO "memberOf", groupID); compareRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); CompareResult compareResult = getConnection().compare(compareRequest); Loading @@ -337,11 +342,23 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO User<X500Principal> getMember(DN userDN) throws UserNotFoundException, LDAPException { SearchResultEntry searchResult = getConnection().getEntry( userDN.toNormalizedString(), Filter filter = Filter.createEqualityFilter("entrydn", userDN.toNormalizedString()); SearchRequest searchRequest = new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, filter, (String[]) this.attribType.values().toArray( new String[this.attribType.values().size()])); searchRequest.addControl( new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); if (searchResult == null) { String msg = "User not found " + userDN; Loading Loading @@ -373,7 +390,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO searchField, new String[] {"entrydn"}); searchRequest.addControl( new ProxiedAuthorizationV1RequestControl(getSubjectDN())); new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); Loading
projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java +11 −9 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ package ca.nrc.cadc.ac.server.ldap; import static ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest.config; import static org.junit.Assert.assertTrue; import java.security.PrivilegedExceptionAction; Loading @@ -84,13 +85,14 @@ import com.unboundid.ldap.sdk.LDAPConnection; public class LdapDAOTest { LdapConfig config = new LdapConfig( "mach275.cadc.dao.nrc.ca", 389, "uid=webproxy,ou=administrators,ou=topologymanagement,o=netscaperoot", "go4it", "ou=Users,ou=ds,dc=canfar,dc=net", "ou=Groups,ou=ds,dc=canfar,dc=net", "ou=DeletedGroups,ou=ds,dc=canfar,dc=net"); static String server = "mach275.cadc.dao.nrc.ca"; static int port = 389; static String adminDN = "uid=webproxy,ou=administrators,ou=topologymanagement,o=netscaperoot"; static String adminPW = "go4it"; static String userBaseDN = "ou=Users,ou=ds,dc=canfartest,dc=net"; static String groupBaseDN = "ou=Groups,ou=ds,dc=canfartest,dc=net"; LdapConfig config = new LdapConfig(server, port, adminDN, adminPW, userBaseDN, groupBaseDN); @Test public void testLdapBindConnection() throws Exception Loading @@ -99,7 +101,7 @@ public class LdapDAOTest //LdapUserDAO<X500Principal> userDAO = new LdapUserDAO<X500Principal>(); // User authenticated with HttpPrincipal HttpPrincipal httpPrincipal = new HttpPrincipal("cadcauthtest2"); HttpPrincipal httpPrincipal = new HttpPrincipal("CadcDaoTest1"); Subject subject = new Subject(); subject.getPrincipals().add(httpPrincipal); Loading @@ -125,7 +127,7 @@ public class LdapDAOTest X500Principal subjPrincipal = new X500Principal( "cn=cadc authtest2 10635,ou=cadc,o=hia"); "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"); subject = new Subject(); subject.getPrincipals().add(subjPrincipal); Loading