diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java index 3c55bae060baf96845d189eb5106dfa468976234..ad7838c4fbeef26b6dd1f9f1d7f21a6a376d1d14 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java @@ -161,5 +161,5 @@ public abstract interface GroupPersistence<T extends Principal> String groupID) throws UserNotFoundException, GroupNotFoundException, TransientException, AccessControlException; - + } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java index 8db06efab2dc59e6f990b921b89c5fdd34157368..703a3d62a170221b4a4ef875e4596c4ffc8880f9 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java @@ -68,10 +68,10 @@ */ package ca.nrc.cadc.ac.server; -import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.net.TransientException; +import com.unboundid.ldap.sdk.DN; import java.security.AccessControlException; import java.security.Principal; import java.util.Collection; @@ -90,21 +90,25 @@ public abstract interface UserPersistence<T extends Principal> * @throws AccessControlException If the operation is not permitted. */ public abstract User<T> getUser(T userID) - throws UserNotFoundException, TransientException, AccessControlException; - + throws UserNotFoundException, TransientException, + AccessControlException; + /** * Get all groups the user specified by userID belongs to. * * @param userID The userID. + * @param isAdmin return only admin Groups when true, else return non-admin + * Groups. * - * @return Collection of Group instances. + * @return Collection of group DN. * * @throws UserNotFoundException when the user is not found. * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public abstract Collection<Group> getUserGroups(T userID) - throws UserNotFoundException, TransientException, AccessControlException; + public abstract Collection<DN> getUserGroups(T userID, boolean isAdmin) + throws UserNotFoundException, TransientException, + AccessControlException; /** * Check whether the user is a member of the group. diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java index 970da4800abe2fff9ece0803fa6503ce3576eb50..d418cc36f9e6a9db5f7e7652839a744f78c5e296 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java @@ -162,10 +162,14 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO "Support for groups properties not available"); } - Group inactiveGroup = getInactiveGroup(group); - if (inactiveGroup != null) + try + { + getInactiveGroup(group); + return reactivateGroup(group); + } + catch (GroupNotFoundException e) { - return reactiveGroup(group, inactiveGroup); + // ignore } DN ownerDN = userPersist.getUserDN(group.getOwner()); @@ -197,7 +201,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO { e.printStackTrace(); throw new RuntimeException(e); - } + } } } @@ -247,43 +251,52 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } private Group getInactiveGroup(final Group group) - throws AccessControlException, UserNotFoundException, LDAPException + throws AccessControlException, UserNotFoundException, + GroupNotFoundException { - Group inactiveGroup = - getInactiveGroup(getGroupDN(group.getID()), group.getID()); - - if (inactiveGroup == null) - { - return null; - } - - if (!group.getOwner().equals(inactiveGroup.getOwner())) - { - throw new AccessControlException( - "Inactive group not owned be requestor"); - } - - Group inactiveAdminGroup = - getInactiveGroup(getAdminGroupDN(group.getID()), group.getID()); - - if (inactiveAdminGroup == null) + Group inactiveGroup; + try { - throw new RuntimeException("BUG: adminGroup not found for group " + - group.getID()); - } - - if (!group.getOwner().equals(inactiveAdminGroup.getOwner())) + inactiveGroup = getInactiveGroup( + getGroupDN(group.getID()), group.getID()); + + if (inactiveGroup == null) + { + return null; + } + + if (!group.getOwner().equals(inactiveGroup.getOwner())) + { + throw new AccessControlException( + "Inactive group not owned be requestor"); + } + + Group inactiveAdminGroup = getInactiveGroup( + getAdminGroupDN(group.getID()), group.getID()); + + if (inactiveAdminGroup == null) + { + throw new RuntimeException( + "BUG: adminGroup not found for group " + group.getID()); + } + + if (!group.getOwner().equals(inactiveAdminGroup.getOwner())) + { + throw new RuntimeException( + "Bug: adminGroup owner doesn't match " + + "group owner for group " + group.getID()); + } + return inactiveGroup; + } + catch (LDAPException e) { - throw new RuntimeException("Bug: adminGroup owner doesn't match " + - "group owner for group " + - group.getID()); + // TODO Auto-generated catch block + throw new RuntimeException("BUG: LDAP Exception: ", e); } - - return inactiveGroup; } private Group getInactiveGroup(final DN groupDN, final String groupID) - throws UserNotFoundException, LDAPException + throws UserNotFoundException, LDAPException, GroupNotFoundException { Filter filter = Filter.createANDFilter( Filter.createEqualityFilter("cn", groupID), @@ -304,7 +317,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO { String msg = "Inactive Group not found " + groupID; logger.debug(msg); - return null; + throw new GroupNotFoundException(msg); } String groupCN = searchResult.getAttributeValue("cn"); @@ -315,34 +328,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO return new Group(groupCN, owner); } - private Group reactiveGroup(final Group newGroup, final Group inactiveGroup) - throws UserNotFoundException, LDAPException, TransientException + private Group reactivateGroup(final Group group) + throws UserNotFoundException, LDAPException, TransientException, + AccessControlException, GroupNotFoundException { - Group group = reactiveGroup(getGroupDN(newGroup.getID()), newGroup, - inactiveGroup); - Group adminGroup = reactiveGroup(getGroupDN(newGroup.getID()), newGroup, - inactiveGroup); - return group; - } - - private Group reactiveGroup(final DN groupDN, final Group newGroup, - final Group inactiveGroup) - throws UserNotFoundException, LDAPException, TransientException - { - List<Modification> mods = new ArrayList<Modification>(); - mods.add(new Modification(ModificationType.DELETE, "nsaccountlock")); - - Group modifiedGroup = modifyGroup(groupDN, newGroup, inactiveGroup, - mods); - Group activatedGroup = new ActivatedGroup(modifiedGroup.getID(), - modifiedGroup.getOwner()); - activatedGroup.description = modifiedGroup.description; - activatedGroup.getProperties().addAll(modifiedGroup.getProperties()); - activatedGroup.getGroupMembers().addAll(modifiedGroup.getGroupMembers()); - activatedGroup.getUserMembers().addAll(modifiedGroup.getUserMembers()); - activatedGroup.getGroupAdmins().addAll(modifiedGroup.getGroupAdmins()); - activatedGroup.getUserAdmins().addAll(modifiedGroup.getUserAdmins()); - return activatedGroup; + return modifyGroup(group, true); } /** @@ -503,7 +493,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO /** * Modify the given group. * - * @param group The group to update. + * @param group The group to update. It must be an existing group * * @return The newly updated group. * @@ -516,171 +506,107 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO throws GroupNotFoundException, TransientException, AccessControlException, UserNotFoundException { - DN groupDN = getGroupDN(group.getID()); - Group oldGroup = getGroup(groupDN, group.getID(), true); - Group newGroup = modifyGroup(groupDN, group, oldGroup, null); - - DN adminGroupDN = getAdminGroupDN(group.getID()); - Group oldAdminGroup = getGroup(adminGroupDN, group.getID(), true); - Group newAdminGroup = modifyGroup(adminGroupDN, group, oldAdminGroup, - null); - - newGroup.getGroupAdmins().addAll(newAdminGroup.getGroupAdmins()); - newGroup.getUserAdmins().addAll(newAdminGroup.getUserAdmins()); - - return newGroup; + return modifyGroup(group, false); } - private Group modifyGroup(final DN groupDN, final Group newGroup, - final Group oldGroup, - final List<Modification> modifications) + private Group modifyGroup(final Group group, boolean withActivate) throws UserNotFoundException, TransientException, - AccessControlException + AccessControlException, GroupNotFoundException { - if (!newGroup.getProperties().isEmpty()) + if (!group.getProperties().isEmpty()) { throw new UnsupportedOperationException( "Support for groups properties not available"); } - - List<Modification> mods = new ArrayList<Modification>(); - if (modifications != null) - { - mods.addAll(modifications); - } - - if (newGroup.description == null && oldGroup.description != null) - { - mods.add(new Modification(ModificationType.DELETE, "description")); - } - else if (newGroup.description != null && oldGroup.description == null) + + // check if group exists + if (withActivate) { - mods.add(new Modification(ModificationType.ADD, "description", - newGroup.description)); + getInactiveGroup(group); } - else if (newGroup.description != null && oldGroup.description != null) + else { - mods.add(new Modification(ModificationType.REPLACE, "description", - newGroup.description)); + getGroup(group.getID()); } - List<String> newMembers = new ArrayList<String>(); - for (User<?> member : newGroup.getUserMembers()) + List<Modification> mods = new ArrayList<Modification>(); + List<Modification> adminMods = new ArrayList<Modification>(); + if (withActivate) { - if (!oldGroup.getUserMembers().remove(member)) - { - DN memberDN; - try - { - memberDN = userPersist.getUserDN(member); - } - catch (LDAPException e) - { - throw new UserNotFoundException( - "User not found " + member.getUserID()); - } - newMembers.add(memberDN.toNormalizedString()); - } + mods.add(new Modification(ModificationType.DELETE, "nsaccountlock")); + adminMods.add(new Modification(ModificationType.DELETE, "nsaccountlock")); } - for (Group gr : newGroup.getGroupMembers()) - { - if (gr.equals(newGroup)) - { - throw new IllegalArgumentException( - "cyclical reference from group member to group"); - } - if (!oldGroup.getGroupMembers().remove(gr)) - { - DN grDN = getGroupDN(gr.getID()); - newMembers.add(grDN.toNormalizedString()); - } - } - for (User<?> member : newGroup.getUserAdmins()) - { - if (!oldGroup.getUserAdmins().remove(member)) - { - DN memberDN; - try - { - memberDN = userPersist.getUserDN(member); - } - catch (LDAPException e) - { - throw new UserNotFoundException( - "User not found " + member.getUserID()); - } - newMembers.add(memberDN.toNormalizedString()); - } - } - for (Group gr : newGroup.getGroupAdmins()) + if (group.description == null) { - if (gr.equals(newGroup)) - { - throw new IllegalArgumentException( - "cyclical reference from group member to group"); - } - - if (!oldGroup.getGroupAdmins().remove(gr)) - { - DN grDN = getGroupDN(gr.getID()); - newMembers.add(grDN.toNormalizedString()); - } + mods.add(new Modification(ModificationType.REPLACE, "description")); } - - if (!newMembers.isEmpty()) + else { - mods.add(new Modification(ModificationType.ADD, "uniquemember", - (String[]) newMembers.toArray(new String[newMembers.size()]))); + mods.add(new Modification(ModificationType.REPLACE, "description", group.description)); } - List<String> delMembers = new ArrayList<String>(); - for (User<?> member : oldGroup.getUserMembers()) + List<String> newMembers = new ArrayList<String>(); + for (User<?> member : group.getUserMembers()) { DN memberDN; try { - memberDN = this.userPersist.getUserDN(member); - } + memberDN = userPersist.getUserDN(member); + } catch (LDAPException e) { - throw new UserNotFoundException( - "User not found " + member.getUserID()); + throw new UserNotFoundException("User not found " + + member.getUserID()); } - delMembers.add(memberDN.toNormalizedString()); + newMembers.add(memberDN.toNormalizedString()); } - for (Group gr : oldGroup.getGroupMembers()) + for (Group gr : group.getGroupMembers()) { - DN grDN = getGroupDN(gr.getID()); - delMembers.add(grDN.toNormalizedString()); + DN grDN = getGroupDN(gr.getID()); + newMembers.add(grDN.toNormalizedString()); } - for (User<?> member : oldGroup.getUserAdmins()) + List<String> newAdmins = new ArrayList<String>(); + for (User<?> member : group.getUserAdmins()) { DN memberDN; try { - memberDN = this.userPersist.getUserDN(member); + memberDN = userPersist.getUserDN(member); } catch (LDAPException e) { throw new UserNotFoundException( "User not found " + member.getUserID()); } - delMembers.add(memberDN.toNormalizedString()); + newAdmins.add(memberDN.toNormalizedString()); } - for (Group gr : oldGroup.getGroupAdmins()) + for (Group gr : group.getGroupAdmins()) { DN grDN = getGroupDN(gr.getID()); - delMembers.add(grDN.toNormalizedString()); + newMembers.add(grDN.toNormalizedString()); } + + mods.add(new Modification(ModificationType.REPLACE, "uniquemember", + (String[]) newMembers.toArray(new String[newMembers.size()]))); + adminMods.add(new Modification(ModificationType.REPLACE, "uniquemember", + (String[]) newAdmins.toArray(new String[newAdmins.size()]))); - if (!delMembers.isEmpty()) + // modify admin group first + ModifyRequest modifyRequest = new ModifyRequest(getAdminGroupDN(group.getID()), adminMods); + try { - mods.add(new Modification(ModificationType.DELETE, "uniquemember", - (String[]) delMembers.toArray(new String[delMembers.size()]))); + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LDAPResult result = getConnection().modify(modifyRequest); } - - ModifyRequest modifyRequest = new ModifyRequest(groupDN, mods); + catch (LDAPException e1) + { + throw new RuntimeException("LDAP problem", e1); + } + // modify the group itself now + modifyRequest = new ModifyRequest(getGroupDN(group.getID()), mods); try { modifyRequest.addControl( @@ -694,12 +620,19 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } try { - return getGroup(newGroup.getID()); + if (withActivate) + { + return new ActivatedGroup(getGroup(group.getID())); + } + else + { + return getGroup(group.getID()); + } } catch (GroupNotFoundException e) { throw new RuntimeException( - "BUG: modified group not found (" + groupDN + ")"); + "BUG: modified group not found (" + group.getID() + ")"); } } @@ -801,24 +734,38 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO throw new TransientException("Error getting user", e); } + Collection<DN> groupDNs = new HashSet<DN>(); if (role == Role.OWNER) { - return getOwnerGroups(user, userDN, groupID); + groupDNs.addAll(getOwnerGroups(user, userDN, groupID)); } else if (role == Role.MEMBER) { - return getMemberGroups(user, userDN, groupID); + groupDNs.addAll(getMemberGroups(user, userDN, groupID, false)); } else if (role == Role.ADMIN) { - return getAdminGroups(user, userDN, groupID); + groupDNs.addAll(getMemberGroups(user, userDN, groupID, true)); + } + + Collection<Group> groups = new HashSet<Group>(); + try + { + for (DN groupDN : groupDNs) + { + groups.add(getGroup(groupDN)); + } + } + catch (LDAPException e) + { + throw new TransientException("Error getting group", e); } - throw new IllegalArgumentException("Unknown role " + role); + return groups; } - protected Collection<Group> getOwnerGroups(final User<T> user, - final DN userDN, - final String groupID) + protected Collection<DN> getOwnerGroups(final User<T> user, + final DN userDN, + final String groupID) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { @@ -834,31 +781,20 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } SearchRequest searchRequest = new SearchRequest( - config.getGroupsDN(), SearchScope.SUB, filter, - new String[] {"cn", "description", "modifytimestamp"}); + config.getGroupsDN(), SearchScope.SUB, filter, "entrydn"); searchRequest.addControl( new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString())); - Collection<Group> groups = new ArrayList<Group>(); + Collection<DN> groupDNs = new HashSet<DN>(); SearchResult results = getConnection().search(searchRequest); for (SearchResultEntry result : results.getSearchEntries()) { - String groupName = result.getAttributeValue("cn"); - // Ignore existing illegal group names. - try - { - Group group = new Group(groupName, user); - group.description = result.getAttributeValue("description"); - group.lastModified = - result.getAttributeValueAsDate("modifytimestamp"); - groups.add(group); - } - catch (IllegalArgumentException ignore) { } + String entryDN = result.getAttributeValue("entrydn"); + groupDNs.add(new DN(entryDN)); } - - return groups; + return groupDNs; } catch (LDAPException e1) { @@ -869,111 +805,39 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } } - protected Collection<Group> getMemberGroups(final User<T> user, - final DN userDN, - final String groupID) + protected Collection<DN> getMemberGroups(final User<T> user, + final DN userDN, + final String groupID, + final boolean isAdmin) throws TransientException, AccessControlException, GroupNotFoundException, UserNotFoundException { + Collection<DN> groups = new HashSet<DN>(); if (groupID != null) { - String groupDN = getGroupDN(groupID).toNormalizedString(); - Collection<Group> groups = new ArrayList<Group>(); - if (userPersist.isMember(user.getUserID(), groupDN)) + DN groupDN; + if (isAdmin) { - groups.add(getGroup(groupID, false)); + groupDN = getAdminGroupDN(groupID); } - return groups; - } - else - { - try + else { - Collection<Group> memberGroups = - userPersist.getUserGroups(user.getUserID()); - - List<Filter> filters = new ArrayList<Filter>(); - for (Group group : memberGroups) - { - filters.add(Filter.createEqualityFilter("cn", - group.getID())); - } - - Filter filter = Filter.createORFilter(filters); - SearchRequest searchRequest = - new SearchRequest(config.getAdminGroupsDN(), - SearchScope.SUB, filter, "cn"); - - SearchResult results = getConnection().search(searchRequest); - for (SearchResultEntry result : results.getSearchEntries()) - { - String groupName = result.getAttributeValue("cn"); - for (Group group : memberGroups) - { - if (group.getID().equals(groupName)) - { - memberGroups.remove(group); - } - } - } - return memberGroups; - } - catch (LDAPException e) - { - throw new TransientException(e.getDiagnosticMessage()); + groupDN = getGroupDN(groupID); } - } - } - - protected Collection<Group> getAdminGroups(final User<T> user, - final DN userDN, - final String groupID) - throws TransientException, AccessControlException, - GroupNotFoundException, UserNotFoundException - { - if (groupID != null) - { - String adminGroupDN = getAdminGroupDN(groupID).toNormalizedString(); - Collection<Group> groups = new ArrayList<Group>(); - if (userPersist.isMember(user.getUserID(), adminGroupDN)) + if (userPersist.isMember(user.getUserID(), + groupDN.toNormalizedString())) { - groups.add(getGroup(groupID, false)); + groups.add(groupDN); } - return groups; } else { - try - { - Collection<Group> memberGroups = - userPersist.getUserGroups(user.getUserID()); - - List<Filter> filters = new ArrayList<Filter>(); - for (Group group : memberGroups) - { - filters.add(Filter.createEqualityFilter("cn", - group.getID())); - } - - Filter filter = Filter.createORFilter(filters); - SearchRequest searchRequest = - new SearchRequest(config.getAdminGroupsDN(), - SearchScope.SUB, filter, "cn"); - - SearchResult results = getConnection().search(searchRequest); - Collection<Group> adminGroups = new HashSet<Group>(); - for (SearchResultEntry result : results.getSearchEntries()) - { - String groupName = result.getAttributeValue("cn"); - adminGroups.add(getGroup(groupName, false)); - } - return adminGroups; - } - catch (LDAPException e) - { - throw new TransientException(e.getDiagnosticMessage()); - } + Collection<DN> memberGroupDNs = + userPersist.getUserGroups(user.getUserID(), isAdmin); + groups.addAll(memberGroupDNs); + logger.debug("# groups found: " + memberGroupDNs.size()); } + return groups; } /** @@ -984,26 +848,25 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO * @return * @throws com.unboundid.ldap.sdk.LDAPException * @throws ca.nrc.cadc.ac.GroupNotFoundException - * @throws ca.nrc.cadc.ac.UserNotFoundException */ -// protected Group getGroup(final 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 Group getGroup(final DN groupDN) + throws LDAPException, GroupNotFoundException + { + 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; + } /** * diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java index 91c6372c9ad7786e18b16e544a8098969b0f7f22..8bdb18d2383a88625c172fb2f183df69410c6cff 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java @@ -191,5 +191,5 @@ public class LdapGroupPersistence<T extends Principal> } } } - + } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java index 90caef285ecec87b1399708f7ed35a5c6ad6d58e..3c0a0e7392f5e5d86c7a40722d31620dd9d79e5d 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java @@ -192,6 +192,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * Get all groups the user specified by userID belongs to. * * @param userID The userID. + * @param isAdmin * * @return Collection of Group instances. * @@ -199,7 +200,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public Collection<Group> getUserGroups(T userID) + public Collection<DN> getUserGroups(final T userID, final boolean isAdmin) throws UserNotFoundException, TransientException, AccessControlException { try @@ -211,7 +212,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO "Unsupported principal type " + userID.getClass()); } - User<T> user = getUser(userID); + User<T> user = getUser(userID); Filter filter = Filter.createANDFilter( Filter.createEqualityFilter(searchField, user.getUserID().getName()), @@ -219,7 +220,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO SearchRequest searchRequest = new SearchRequest(config.getUsersDN(), SearchScope.SUB, - filter, new String[] {"memberOf"}); + filter, "memberOf"); searchRequest.addControl( new ProxiedAuthorizationV2RequestControl("dn:" + @@ -228,31 +229,37 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); - Collection<Group> groups = new HashSet<Group>(); + DN parentDN; + if (isAdmin) + { + parentDN = new DN(config.getAdminGroupsDN()); + } + else + { + parentDN = new DN(config.getGroupsDN()); + } + + Collection<DN> groupDNs = new HashSet<DN>(); if (searchResult != null) { - String[] members = - searchResult.getAttributeValues("memberOf"); + String[] members = searchResult.getAttributeValues("memberOf"); if (members != null) { for (String member : members) { - String groupCN = DN.getRDNString(member); - int index = groupCN.indexOf("="); - String groupName = groupCN.substring(index + 1); - // Ignore existing illegal group names. - try + DN groupDN = new DN(member); + if (groupDN.isDescendantOf(parentDN, false)) { - groups.add(new Group(groupName, user)); + groupDNs.add(groupDN); } - catch (IllegalArgumentException ignore) { } } } } - return groups; + return groupDNs; } catch (LDAPException e) { + e.printStackTrace(); // TODO check which LDAP exceptions are transient and which // ones are // access control @@ -272,7 +279,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public boolean isMemberX(T userID, String groupID) + public boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException { @@ -317,43 +324,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } } - public boolean isMember(T userID, String groupDN) - throws UserNotFoundException, TransientException, - AccessControlException - { - try - { - String searchField = (String) userLdapAttrib.get(userID.getClass()); - if (searchField == null) - { - throw new IllegalArgumentException( - "Unsupported principal type " + userID.getClass()); - } - - User<T> user = getUser(userID); - DN userDN = getUserDN(user); - - CompareRequest compareRequest = - new CompareRequest(userDN.toNormalizedString(), - "memberOf", groupDN); - - compareRequest.addControl( - new ProxiedAuthorizationV2RequestControl("dn:" + - getSubjectDN().toNormalizedString())); - - CompareResult compareResult = - getConnection().compare(compareRequest); - return compareResult.compareMatched(); - } - catch (LDAPException e) - { - // TODO check which LDAP exceptions are transient and which - // ones are - // access control - throw new TransientException("Error getting the user", e); - } - } - /** * Returns a member user identified by the X500Principal only. The * returned object has the fields required by the GMS. diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java index ae28f5c12315d393aa0b3a87cc329be79344f598..8511d254f2ab164ad4428e9ab929f9e782bf852b 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java @@ -68,11 +68,11 @@ */ package ca.nrc.cadc.ac.server.ldap; -import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.net.TransientException; +import com.unboundid.ldap.sdk.DN; import java.security.AccessControlException; import java.security.Principal; import java.util.Collection; @@ -130,21 +130,23 @@ public class LdapUserPersistence<T extends Principal> * Get all groups the user specified by userID belongs to. * * @param userID The userID. + * @param isAdmin return only admin Groups when true, else return non-admin + * Groups. * - * @return Collection of Group instances. + * @return Collection of Group DN. * * @throws UserNotFoundException when the user is not found. * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public Collection<Group> getUserGroups(T userID) + public Collection<DN> getUserGroups(T userID, boolean isAdmin) throws UserNotFoundException, TransientException, AccessControlException { LdapUserDAO<T> userDAO = null; try { userDAO = new LdapUserDAO<T>(this.config); - Collection<Group> ret = userDAO.getUserGroups(userID); + Collection<DN> ret = userDAO.getUserGroups(userID, isAdmin); return ret; } finally diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java index 8a675ee56ae32f2a7d85f21df3c1dc2c66ffcb65..2c68a1e61958dac8d9dd2bb946d114eff633330b 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java @@ -70,11 +70,11 @@ public class LdapGroupDAOTest static int port = 389; static String adminDN = "uid=webproxy,ou=webproxy,ou=topologymanagement,o=netscaperoot"; static String adminPW = "go4it"; - static String usersDN = "ou=Users,ou=ds,dc=canfartest,dc=net"; - static String groupsDN = "ou=Groups,ou=ds,dc=canfartest,dc=net"; +// static String usersDN = "ou=Users,ou=ds,dc=canfartest,dc=net"; +// static String groupsDN = "ou=Groups,ou=ds,dc=canfartest,dc=net"; static String adminGroupsDN = "ou=adminGroups,ou=ds,dc=canfartest,dc=net"; - //static String usersDN = "ou=Users,ou=ds,dc=canfar,dc=net"; - //static String groupsDN = "ou=Groups,ou=ds,dc=canfar,dc=net"; + static String usersDN = "ou=Users,ou=ds,dc=canfar,dc=net"; + static String groupsDN = "ou=Groups,ou=ds,dc=canfar,dc=net"; static String daoTestDN1 = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"; static String daoTestDN2 = "cn=cadcdaotest2,ou=cadc,o=hia,c=ca"; @@ -275,15 +275,13 @@ public class LdapGroupDAOTest }); } - // TODO: add test passing in groupID @Test public void testSearchMemberGroups() throws Exception { - final String testGroup1ID = getGroupID(); - - final String testGroup2ID = getGroupID(); + final String groupID = getGroupID(); + final String testGroup1ID = groupID + "-1"; + final String testGroup2ID = groupID + "-2"; - Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() { public Object run() throws Exception @@ -293,11 +291,12 @@ public class LdapGroupDAOTest Group testGroup1 = new Group(testGroup1ID, daoTestUser1); testGroup1.getUserMembers().add(daoTestUser2); testGroup1 = getGroupDAO().addGroup(testGroup1); + log.debug("add group: " + testGroup1ID); Group testGroup2 = new Group(testGroup2ID, daoTestUser1); testGroup2.getUserMembers().add(daoTestUser2); testGroup2 = getGroupDAO().addGroup(testGroup2); - + log.debug("add group: " + testGroup2ID); } catch (Exception e) { @@ -325,6 +324,7 @@ public class LdapGroupDAOTest boolean found2 = false; for (Group group : groups) { + log.debug("member group: " + group.getID()); if (group.getID().equals(testGroup1ID)) { found1 = true; @@ -342,6 +342,12 @@ public class LdapGroupDAOTest { fail("Test group 2 not found"); } + + groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.MEMBER, testGroup1ID); + assertNotNull(groups); + assertTrue(groups.size() == 1); + assertTrue(groups.iterator().next().getID().equals(testGroup1ID)); } catch (Exception e) { @@ -368,45 +374,97 @@ public class LdapGroupDAOTest } }); } - - // TODO: add test passing in groupID + // @Test public void testSearchAdminGroups() throws Exception { - // do everything as owner + final String groupID = getGroupID(); + final String testGroup1ID = groupID + ".1"; + final String testGroup2ID = groupID + ".2"; + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { try - { - Group expectedGroup = new Group("CadcDaoTestGroup1"); + { + Group testGroup1 = new Group(testGroup1ID, daoTestUser1); + testGroup1.getUserAdmins().add(daoTestUser2); + testGroup1 = getGroupDAO().addGroup(testGroup1); + log.debug("add group: " + testGroup1ID); + Group testGroup2 = new Group(testGroup2ID, daoTestUser1); + testGroup2.getUserAdmins().add(daoTestUser2); + testGroup2 = getGroupDAO().addGroup(testGroup2); + log.debug("add group: " + testGroup2ID); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { Collection<Group> groups = - getGroupDAO().getGroups(daoTestUser2.getUserID(), - Role.ADMIN, null); - System.out.println("# groups found: " + groups.size()); + getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.ADMIN, null); - boolean found = false; + log.debug("# groups found: " + groups.size()); + assertNotNull(groups); + assertTrue(groups.size() >= 2); + + boolean found1 = false; + boolean found2 = false; for (Group group : groups) { - System.out.println("found group: " + group.getID()); - // get the group to get the owner - // (not returned for RW groups) - group = getGroupDAO().getGroup(group.getID()); - if (!group.getOwner().equals(daoTestUser2)) + log.debug("admin group: " + group.getID()); + if (group.getID().equals(testGroup1ID)) { - fail("returned group with wrong owner"); + found1 = true; } - if (group.equals(expectedGroup)) + if (group.getID().equals(testGroup2ID)) { - found = true; + found2 = true; } } - if (!found) + if (!found1) { - fail(""); + fail("Test group 1 not found"); } + if (!found2) + { + fail("Test group 2 not found"); + } + + groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.ADMIN, testGroup1ID); + assertNotNull(groups); + assertTrue(groups.size() == 1); + assertTrue(groups.iterator().next().getID().equals(testGroup1ID)); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(testGroup1ID); + getGroupDAO().deleteGroup(testGroup2ID); } catch (Exception e) { @@ -521,15 +579,6 @@ public class LdapGroupDAOTest public Object run() throws Exception { getGroupDAO().addGroup(new Group(groupID, daoTestUser1)); - -// try -// { -// getGroupDAO().modifyGroup(new Group(groupID, unknownUser)); -// fail("modifyGroup with unknown user should throw " + -// "UserNotFoundException"); -// } -// catch (UserNotFoundException ignore) {} - try { getGroupDAO().modifyGroup(new Group("foo", daoTestUser1)); diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java index f02c0f12c21689c61b6625bac768e3fd91efe835..6bda5b89871e4aaa8bbd6ffe71f3dc56cfa6e809 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java @@ -172,7 +172,7 @@ public class LdapUserDAOTest /** * Test of getUserGroups method, of class LdapUserDAO. */ -// @Test + @Test public void testGetUserGroups() throws Exception { Subject subject = new Subject(); @@ -185,11 +185,17 @@ public class LdapUserDAOTest { try { - Collection<Group> groups = getUserDAO().getUserGroups(testUser.getUserID()); + Collection<DN> groups = getUserDAO().getUserGroups(testUser.getUserID(), false); + assertNotNull(groups); + assertTrue(!groups.isEmpty()); + for (DN groupDN : groups) + log.debug(groupDN); + + groups = getUserDAO().getUserGroups(testUser.getUserID(), true); assertNotNull(groups); assertTrue(!groups.isEmpty()); - for (Group group : groups) - log.debug(group); + for (DN groupDN : groups) + log.debug(groupDN); return null; } @@ -204,7 +210,7 @@ public class LdapUserDAOTest /** * Test of getUserGroups method, of class LdapUserDAO. */ -// @Test + @Test public void testIsMember() throws Exception { Subject subject = new Subject(); @@ -220,8 +226,8 @@ public class LdapUserDAOTest boolean isMember = getUserDAO().isMember(testUser.getUserID(), "foo"); assertFalse(isMember); - String groupID = "cn=cadcdaotestgroup,cn=groups,ou=ds,dc=canfartest,dc=net"; - isMember = getUserDAO().isMember(testUser.getUserID(), groupID); + String groupDN = "cn=cadcdaotestgroup1,ou=groups,ou=ds,dc=canfartest,dc=net"; + isMember = getUserDAO().isMember(testUser.getUserID(), groupDN); assertTrue(isMember); return null; @@ -234,7 +240,6 @@ public class LdapUserDAOTest }); } - /** * Test of getMember. */ @@ -262,7 +267,6 @@ public class LdapUserDAOTest } }); - // should also work as a different user subject = new Subject(); subject.getPrincipals().add(new HttpPrincipal("CadcDaoTest2")); @@ -286,7 +290,6 @@ public class LdapUserDAOTest }); } - private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2) { assertEquals(user1, user2); diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java index 189088c9de5af0f082e88032c846ae859c18c4ba..22e445ede8750b77db6dd5f0bc07db03420531db 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java @@ -68,19 +68,18 @@ */ package ca.nrc.cadc.ac; -import java.security.Principal; public class ActivatedGroup extends Group { - - public ActivatedGroup(String groupID) - { - super(groupID); - } - - public ActivatedGroup(String groupID, User<? extends Principal> owner) + public ActivatedGroup(Group group) { - super(groupID, owner); + super(group.getID(), group.getOwner()); + this.description = group.description; + this.properties = group.getProperties(); + this.lastModified = group.lastModified; + this.getUserMembers().addAll(group.getUserMembers()); + this.getGroupMembers().addAll(group.getGroupMembers()); + this.getUserAdmins().addAll(group.getUserAdmins()); + this.getGroupAdmins().addAll(group.getGroupAdmins()); } - }