Skip to content
Snippets Groups Projects
Commit 0945f3d9 authored by Brian Major's avatar Brian Major
Browse files

Merge branch 's1651' of /usr/cadc/dev/git/wopencadc into s1651

parents 3310dfa1 79dc8a3a
No related branches found
No related tags found
No related merge requests found
Showing
with 818 additions and 646 deletions
......@@ -86,9 +86,11 @@ 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_ADMIN_GROUPS_DN = "adminGroupsDn";
private String usersDN;
private String groupsDN;
private String adminGroupsDN;
private String server;
private int port;
private String adminUserDN;
......@@ -156,18 +158,26 @@ public class LdapConfig
throw new RuntimeException("failed to read property " +
LDAP_GROUPS_DN);
}
String ldapAdminGroupsDn = config.getProperty(LDAP_ADMIN_GROUPS_DN);
if (!StringUtil.hasText(ldapAdminGroupsDn))
{
throw new RuntimeException("failed to read property " +
LDAP_ADMIN_GROUPS_DN);
}
return new LdapConfig(server, Integer.valueOf(port), ldapAdmin,
ldapPasswd, ldapUsersDn, ldapGroupsDn);
ldapPasswd, ldapUsersDn, ldapGroupsDn,
ldapAdminGroupsDn);
}
public LdapConfig(String server, int port, String adminUserDN,
String adminPasswd, String usersDN, String groupsDN)
String adminPasswd, String usersDN, String groupsDN,
String adminGroupsDN)
{
if (!StringUtil.hasText(server))
{
throw new IllegalArgumentException("Illegal LDAP server name: " +
server);
throw new IllegalArgumentException("Illegal LDAP server name");
}
if (port < 0)
{
......@@ -176,23 +186,23 @@ public class LdapConfig
}
if (!StringUtil.hasText(adminUserDN))
{
throw new IllegalArgumentException("Illegal Admin DN: " +
adminUserDN);
throw new IllegalArgumentException("Illegal Admin DN");
}
if (!StringUtil.hasText(adminPasswd))
{
throw new IllegalArgumentException("Illegal Admin password: " +
adminPasswd);
throw new IllegalArgumentException("Illegal Admin password");
}
if (!StringUtil.hasText(usersDN))
{
throw new IllegalArgumentException("Illegal users LDAP DN: " +
usersDN);
throw new IllegalArgumentException("Illegal users LDAP DN");
}
if (!StringUtil.hasText(groupsDN))
{
throw new IllegalArgumentException("Illegal groups LDAP DN: " +
groupsDN);
throw new IllegalArgumentException("Illegal groups LDAP DN");
}
if (!StringUtil.hasText(adminGroupsDN))
{
throw new IllegalArgumentException("Illegal admin groups LDAP DN");
}
this.server = server;
......@@ -201,6 +211,7 @@ public class LdapConfig
this.adminPasswd = adminPasswd;
this.usersDN = usersDN;
this.groupsDN = groupsDN;
this.adminGroupsDN = adminGroupsDN;
}
public String getUsersDN()
......@@ -212,6 +223,11 @@ public class LdapConfig
{
return this.groupsDN;
}
public String getAdminGroupsDN()
{
return this.adminGroupsDN;
}
public String getServer()
{
......
......@@ -72,8 +72,8 @@ import java.security.AccessControlException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
......@@ -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;
......@@ -151,22 +142,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
throw new IllegalArgumentException("Group owner must be specified");
}
try
{
User<X500Principal> subjectUser =
userPersist.getMember(getSubjectDN());
if (!subjectUser.equals(group.getOwner()))
{
throw new AccessControlException("Group owner must be group " +
" creator");
}
}
catch (LDAPException e)
if (!isCreatorOwner(group.getOwner()))
{
e.printStackTrace();
throw new RuntimeException(e);
throw new AccessControlException("Group owner must be creator");
}
try
{
getGroup(group.getID());
......@@ -175,127 +155,39 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
catch (GroupNotFoundException ex)
{
try
{
try
{
Group inactiveGroup = getInactiveGroup(group.getID());
// Check requestor owns the group.
DN ownerDN = userPersist.getUserDN(group.getOwner());
if (!ownerDN.equals(getSubjectDN()))
{
throw new AccessControlException(
"Unable to activate group " + group.getID() +
" because " + getSubjectDN().toString()
+ " is not the owner");
}
List<Modification> mods = new ArrayList<Modification>();
Modification mod =
new Modification(ModificationType.DELETE,
"nsaccountlock");
mods.add(mod);
Group modifiedGroup = modifyGroup(group, inactiveGroup,
mods);
Group activatedGroup =
new ActivatedGroup(modifiedGroup.getID(),
modifiedGroup.getOwner());
activatedGroup.description = modifiedGroup.description;
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) {}
{
if (!group.getProperties().isEmpty())
{
throw new UnsupportedOperationException(
"Support for groups properties not available");
}
DN ownerDN = userPersist.getUserDN(group.getOwner());
String groupWriteAci = null;
String groupReadAci = null;
if (group.groupWrite != null)
{
DN groupWrite = getGroupDN(group.groupWrite.getID());
groupWriteAci = GROUP_WRITE_ACI.replace(
ACTUAL_GROUP_TOKEN,
groupWrite.toNormalizedString());
}
if (group.groupRead != null)
{
DN groupRead = getGroupDN(group.groupRead.getID());
groupReadAci = GROUP_READ_ACI.replace(
ACTUAL_GROUP_TOKEN,
groupRead.toNormalizedString());
}
// add new group
List<Attribute> attributes = new ArrayList<Attribute>();
attributes.add(new Attribute("objectClass",
"groupofuniquenames"));
attributes.add(new Attribute("cn", group.getID()));
if (group.description != null)
{
attributes.add(new Attribute("description",
group.description));
}
attributes.add(new Attribute("owner",
ownerDN.toNormalizedString()));
// acis
List<String> acis = new ArrayList<String>();
if (groupWriteAci != null)
{
acis.add(groupWriteAci);
}
if (groupReadAci != null)
{
acis.add(groupReadAci);
}
if (!acis.isEmpty())
{
attributes.add(new Attribute("aci",
(String[]) acis.toArray(new String[acis.size()])));
}
List<String> members = new ArrayList<String>();
for (User<?> member : group.getUserMembers())
{
DN memberDN = this.userPersist.getUserDN(member);
members.add(memberDN.toNormalizedString());
}
for (Group gr : group.getGroupMembers())
try
{
DN grDN = getGroupDN(gr.getID());
members.add(grDN.toNormalizedString());
getInactiveGroup(group);
return reactivateGroup(group);
}
if (!members.isEmpty())
catch (GroupNotFoundException e)
{
attributes.add(new Attribute("uniquemember",
(String[]) members.toArray(new String[members.size()])));
// ignore
}
AddRequest addRequest =
new AddRequest(getGroupDN(group.getID()), attributes);
addRequest.addControl(
new ProxiedAuthorizationV2RequestControl(
"dn:" + getSubjectDN().toNormalizedString()));
LDAPResult result = getConnection().add(addRequest);
DN ownerDN = userPersist.getUserDN(group.getOwner());
// add group to groups tree
LDAPResult result = addGroup(getGroupDN(group.getID()),
group.getID(), ownerDN,
group.description,
group.getUserMembers(),
group.getGroupMembers());
// add group to admin groups tree
result = addGroup(getAdminGroupDN(group.getID()),
group.getID(), ownerDN,
group.description,
group.getUserMembers(),
group.getGroupMembers());
try
{
return getGroup(group.getID());
......@@ -309,10 +201,143 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
private LDAPResult addGroup(final DN groupDN, final String groupID,
final DN ownerDN, final String description,
final Set<User<? extends Principal>> users,
final Set<Group> groups)
throws UserNotFoundException, LDAPException
{
// add new group
List<Attribute> attributes = new ArrayList<Attribute>();
Attribute ownerAttribute =
new Attribute("owner", ownerDN.toNormalizedString());
attributes.add(ownerAttribute);
attributes.add(new Attribute("objectClass", "groupofuniquenames"));
attributes.add(new Attribute("cn", groupID));
if (description != null)
{
attributes.add(new Attribute("description", description));
}
List<String> members = new ArrayList<String>();
for (User<? extends Principal> userMember : users)
{
DN memberDN = this.userPersist.getUserDN(userMember);
members.add(memberDN.toNormalizedString());
}
for (Group groupMember : groups)
{
DN memberDN = getGroupDN(groupMember.getID());
members.add(memberDN.toNormalizedString());
}
if (!members.isEmpty())
{
attributes.add(new Attribute("uniquemember",
(String[]) members.toArray(new String[members.size()])));
}
AddRequest addRequest = new AddRequest(groupDN, attributes);
addRequest.addControl(
new ProxiedAuthorizationV2RequestControl(
"dn:" + getSubjectDN().toNormalizedString()));
return getConnection().add(addRequest);
}
private Group getInactiveGroup(final Group group)
throws AccessControlException, UserNotFoundException,
GroupNotFoundException
{
Group inactiveGroup;
try
{
inactiveGroup = getInactiveGroup(getGroupDN(group.getID())
.toNormalizedString(), 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()).toNormalizedString(),
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)
{
// TODO Auto-generated catch block
throw new RuntimeException("BUG: LDAP Exception: ", e);
}
}
private Group getInactiveGroup(final String groupDN, final String groupID)
throws UserNotFoundException, LDAPException, GroupNotFoundException
{
Filter filter = Filter.createANDFilter(
Filter.createEqualityFilter("cn", groupID),
Filter.createEqualityFilter("nsaccountlock", "true"));
SearchRequest searchRequest =
new SearchRequest(groupDN, SearchScope.SUB, filter,
new String[] {"cn", "owner"});
searchRequest.addControl(
new ProxiedAuthorizationV2RequestControl("dn:" +
getSubjectDN().toNormalizedString()));
SearchResultEntry searchResult =
getConnection().searchForEntry(searchRequest);
if (searchResult == null)
{
String msg = "Inactive Group not found " + groupID;
logger.debug(msg);
throw new GroupNotFoundException(msg);
}
String groupCN = searchResult.getAttributeValue("cn");
DN groupOwner = searchResult.getAttributeValueAsDN("owner");
User<X500Principal> owner = userPersist.getMember(groupOwner);
return new Group(groupCN, owner);
}
private Group reactivateGroup(final Group group)
throws UserNotFoundException, LDAPException, TransientException, AccessControlException, GroupNotFoundException
{
return modifyGroup(group, true);
}
/**
* Get the group with the given Group ID.
*
......@@ -323,14 +348,50 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
* @throws GroupNotFoundException If the group was not found.
* @throws TransientException If an temporary, unexpected problem occurred.
*/
public Group getGroup(String groupID)
public Group getGroup(final String groupID)
throws GroupNotFoundException, TransientException,
AccessControlException
{
return getGroup(groupID, true);
}
public Group getGroup(final String groupID, final boolean withMembers)
throws GroupNotFoundException, TransientException,
AccessControlException
{
Group group = getGroup(getGroupDN(groupID), groupID, true);
Group adminGroup = getAdminGroup(getAdminGroupDN(groupID), groupID,
true);
group.getGroupAdmins().addAll(adminGroup.getGroupMembers());
group.getUserAdmins().addAll(adminGroup.getUserMembers());
return group;
}
private Group getGroup(final DN groupDN, final String groupID,
final boolean withMembers)
throws GroupNotFoundException, TransientException,
AccessControlException
{
String [] attributes = new String[] {"entrydn", "cn", "description",
"owner", "uniquemember",
"modifytimestamp"};
return getGroup(groupDN, groupID, withMembers, attributes);
}
private Group getAdminGroup(final DN groupDN, final String groupID,
final boolean withMembers)
throws GroupNotFoundException, TransientException,
AccessControlException
{
String [] attributes = new String[] {"entrydn", "cn", "owner",
"uniquemember"};
return getGroup(groupDN, groupID, withMembers, attributes);
}
private Group getGroup(String groupID, boolean withMembers)
private Group getGroup(final DN groupDN, final String groupID,
final boolean withMembers, String[] attributes)
throws GroupNotFoundException, TransientException,
AccessControlException
{
......@@ -341,28 +402,26 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
Filter.createNOTFilter(
Filter.createEqualityFilter("nsaccountlock", "TRUE")));
SearchRequest searchRequest = new SearchRequest(
config.getGroupsDN(), SearchScope.SUB,
filter, new String[] {"entrydn", "cn", "description",
"owner", "uniquemember", "aci",
"modifytimestamp"});
SearchRequest searchRequest =
new SearchRequest(groupDN.toNormalizedString(),
SearchScope.SUB, filter, attributes);
searchRequest.addControl(
new ProxiedAuthorizationV2RequestControl("dn:" +
getSubjectDN().toNormalizedString()));
SearchResultEntry group =
SearchResultEntry searchResult =
getConnection().searchForEntry(searchRequest);
if (group == null)
if (searchResult == null)
{
String msg = "Group not found " + groupID;
logger.debug(msg);
throw new GroupNotFoundException(groupID);
}
String groupCN = group.getAttributeValue("cn");
DN groupOwner = group.getAttributeValueAsDN("owner");
Date lastModified =
group.getAttributeValueAsDate("modifytimestamp");
String groupCN = searchResult.getAttributeValue("cn");
DN groupOwner = searchResult.getAttributeValueAsDN("owner");
User<X500Principal> owner;
try
......@@ -375,14 +434,22 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
}
Group ldapGroup = new Group(groupCN, owner);
ldapGroup.description = group.getAttributeValue("description");
ldapGroup.lastModified = lastModified;
if (searchResult.hasAttribute("description"))
{
ldapGroup.description =
searchResult.getAttributeValue("description");
}
if (searchResult.hasAttribute("modifytimestamp"))
{
ldapGroup.lastModified =
searchResult.getAttributeValueAsDate("modifytimestamp");
}
if (withMembers)
{
if (group.getAttributeValues("uniquemember") != null)
if (searchResult.getAttributeValues("uniquemember") != null)
{
for (String member : group
for (String member : searchResult
.getAttributeValues("uniquemember"))
{
DN memberDN = new DN(member);
......@@ -391,7 +458,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)
{
......@@ -412,36 +479,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
}
}
}
// TODO not sure this is going to fly...
if (group.getAttributeValues("aci") != null)
{
for (String aci : group.getAttributeValues("aci"))
{
if (aci.contains("Group Read"))
{
// TODO it's gotta be a better way to do this.
String grRead = aci.substring(
aci.indexOf("ldap:///"));
grRead = grRead.substring(grRead.indexOf("cn=") + 3,
grRead.indexOf(','));
Group groupRead = new Group(grRead.trim());
ldapGroup.groupRead = groupRead;
}
else if (aci.contains("Group Write"))
{
// TODO it's gotta be a better way to do this.
String grWrite = aci.substring(
aci.indexOf("ldap:///"));
grWrite = grWrite.substring(grWrite.indexOf("cn=") + 3,
grWrite.indexOf(','));
Group groupWrite = getGroup(grWrite.trim());
ldapGroup.groupWrite = groupWrite;
}
}
}
}
return ldapGroup;
......@@ -458,7 +495,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.
*
......@@ -471,141 +508,108 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
throws GroupNotFoundException, TransientException,
AccessControlException, UserNotFoundException
{
// check if group exists
Group oldGroup = getGroup(group.getID());
return modifyGroup(group, oldGroup, null);
return modifyGroup(group, false);
}
private Group modifyGroup(Group newGroup, Group oldGroup,
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> modifs = new ArrayList<Modification>();
if (modifications != null)
{
modifs.addAll(modifications);
}
if (newGroup.description == null && oldGroup.description != null)
// check if group exists
if (withActivate)
{
modifs.add(new Modification(ModificationType.DELETE,
"description"));
getInactiveGroup(group);
}
else if (newGroup.description != null && oldGroup.description == null)
else
{
modifs.add(new Modification(ModificationType.ADD, "description",
newGroup.description));
getGroup(group.getID());
}
else if (newGroup.description != null && oldGroup.description != null)
List<Modification> mods = new ArrayList<Modification>();
List<Modification> adminMods = new ArrayList<Modification>();
if (withActivate)
{
modifs.add(new Modification(ModificationType.REPLACE, "description",
newGroup.description));
mods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
adminMods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
}
List<String> acis = new ArrayList<String>();
if (newGroup.groupRead != null)
if (group.description == null)
{
if (newGroup.groupRead.equals(newGroup))
{
throw new IllegalArgumentException(
"cyclical reference from groupRead to group");
}
DN readGrDN = getGroupDN(newGroup.groupRead.getID());
acis.add(GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN,
readGrDN.toNormalizedString()));
mods.add(new Modification(ModificationType.REPLACE, "description"));
}
if (newGroup.groupWrite != null)
else
{
if (newGroup.groupWrite.equals(newGroup))
{
throw new IllegalArgumentException(
"cyclical reference from groupWrite to group");
}
DN writeGrDN = getGroupDN(newGroup.groupWrite.getID());
acis.add(GROUP_WRITE_ACI.replace(ACTUAL_GROUP_TOKEN,
writeGrDN.toNormalizedString()));
mods.add(new Modification(ModificationType.REPLACE, "description", group.description));
}
modifs.add(new Modification(ModificationType.REPLACE, "aci", (String[])
acis.toArray(new String[acis.size()])));
List<String> newMembers = new ArrayList<String>();
for (User<?> member : newGroup.getUserMembers())
for (User<?> member : group.getUserMembers())
{
if (!oldGroup.getUserMembers().remove(member))
DN memberDN;
try
{
DN memberDN;
try
{
memberDN = userPersist.getUserDN(member);
}
catch (LDAPException e)
{
throw new UserNotFoundException(
"User not found " + member.getUserID());
}
newMembers.add(memberDN.toNormalizedString());
memberDN = userPersist.getUserDN(member);
}
catch (LDAPException e)
{
throw new UserNotFoundException("User not found "
+ member.getUserID());
}
newMembers.add(memberDN.toNormalizedString());
}
for (Group gr : newGroup.getGroupMembers())
for (Group gr : group.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());
}
}
if (!newMembers.isEmpty())
{
modifs.add(new Modification(ModificationType.ADD, "uniquemember",
(String[]) newMembers.toArray(new String[newMembers.size()])));
}
List<String> delMembers = new ArrayList<String>();
for (User<?> member : oldGroup.getUserMembers())
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.getGroupMembers())
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()])));
// modify admin group first
ModifyRequest modifyRequest = new ModifyRequest(getAdminGroupDN(group.getID()), adminMods);
try
{
modifyRequest.addControl(
new ProxiedAuthorizationV2RequestControl(
"dn:" + getSubjectDN().toNormalizedString()));
LDAPResult result = getConnection().modify(modifyRequest);
}
if (!delMembers.isEmpty())
catch (LDAPException e1)
{
modifs.add(new Modification(ModificationType.DELETE, "uniquemember",
(String[]) delMembers.toArray(new String[delMembers.size()])));
throw new RuntimeException("LDAP problem", e1);
}
ModifyRequest modifyRequest =
new ModifyRequest(getGroupDN(newGroup.getID()), modifs);
// modify the group itself now
modifyRequest = new ModifyRequest(getGroupDN(group.getID()), mods);
try
{
modifyRequest.addControl(
......@@ -619,11 +623,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");
throw new RuntimeException(
"BUG: modified group not found (" + group.getID() + ")");
}
}
......@@ -639,29 +651,37 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
throws GroupNotFoundException, TransientException,
AccessControlException
{
Group group = getGroup(groupID);
deleteGroup(getGroupDN(groupID), groupID, false);
deleteGroup(getAdminGroupDN(groupID), groupID, true);
}
private void deleteGroup(final DN groupDN, final String groupID,
final boolean isAdmin)
throws GroupNotFoundException, TransientException,
AccessControlException
{
Group group = getGroup(groupDN, groupID, false);
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)
if (isAdmin)
{
modifs.add(new Modification(ModificationType.DELETE, "aci"));
if (!group.getGroupAdmins().isEmpty() ||
!group.getUserAdmins().isEmpty())
{
modifs.add(new Modification(ModificationType.DELETE, "uniquemember"));
}
}
if (!group.getGroupMembers().isEmpty() ||
!group.getUserMembers().isEmpty())
else
{
modifs.add(new Modification(ModificationType.DELETE, "uniquemember"));
if (!group.getGroupMembers().isEmpty() ||
!group.getUserMembers().isEmpty())
{
modifs.add(new Modification(ModificationType.DELETE, "uniquemember"));
}
}
ModifyRequest modifyRequest =
new ModifyRequest(getGroupDN(group.getID()), modifs);
ModifyRequest modifyRequest = new ModifyRequest(groupDN, modifs);
try
{
modifyRequest.addControl(
......@@ -726,7 +746,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
}
else if (role == Role.RW)
{
return getRWGroups(user, userDN, groupID);
return getAdminGroups(user, userDN, groupID);
}
throw new IllegalArgumentException("Unknown role " + role);
}
......@@ -793,17 +813,45 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
Collection<Group> groups = new ArrayList<Group>();
if (userPersist.isMember(user.getUserID(), groupID))
{
groups.add(getGroup(groupID));
groups.add(getGroup(groupID, false));
}
return groups;
}
else
{
return userPersist.getUserGroups(user.getUserID());
try
{
Collection<Group> groups =
userPersist.getUserGroups(user.getUserID());
List<Filter> filters = new ArrayList<Filter>();
for (Group group : groups)
{
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");
}
return groups;
}
catch (LDAPException e)
{
throw new TransientException(e.getDiagnosticMessage());
}
}
}
protected Collection<Group> getRWGroups(User<T> user, DN userDN,
protected Collection<Group> getAdminGroups(User<T> user, DN userDN,
String groupID)
throws TransientException, AccessControlException,
GroupNotFoundException, UserNotFoundException
......@@ -829,25 +877,25 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
List<Filter> filters = new ArrayList<Filter>();
for (Group member : queryGroups)
{
// Require both groupRead and groupWrite
if (member.groupRead != null && member.groupWrite != null)
{
DN groupRead = getGroupDN(member.groupRead.getID());
String groupReadAci =
GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN,
groupRead.toNormalizedString());
DN groupWrite = getGroupDN(member.groupRead.getID());
String groupWriteAci =
GROUP_WRITE_ACI.replace(ACTUAL_GROUP_TOKEN,
groupWrite.toNormalizedString());
System.out.println(groupReadAci);
System.out.println(groupWriteAci);
Filter filter = Filter.createANDFilter(
Filter.createEqualityFilter("aci", groupReadAci),
Filter.createEqualityFilter("aci", groupWriteAci));
filters.add(filter);
}
// // Require both groupRead and groupWrite
// if (member.groupRead != null && member.groupWrite != null)
// {
// DN groupRead = getGroupDN(member.groupRead.getID());
// String groupReadAci =
// GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN,
// groupRead.toNormalizedString());
// DN groupWrite = getGroupDN(member.groupRead.getID());
// String groupWriteAci =
// GROUP_WRITE_ACI.replace(ACTUAL_GROUP_TOKEN,
// groupWrite.toNormalizedString());
// System.out.println(groupReadAci);
// System.out.println(groupWriteAci);
//
// Filter filter = Filter.createANDFilter(
// Filter.createEqualityFilter("aci", groupReadAci),
// Filter.createEqualityFilter("aci", groupWriteAci));
// filters.add(filter);
// }
}
Collection<Group> groups = new ArrayList<Group>();
......@@ -895,119 +943,86 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
}
}
protected Collection<Group> getRWGroups2(User<T> user, DN userDN,
String groupID)
throws TransientException, AccessControlException,
GroupNotFoundException, UserNotFoundException
{
try
{
Collection<Group> groups = new ArrayList<Group>();
Collection<Group> queryGroups = new ArrayList<Group>();
if (groupID != null)
{
queryGroups.add(new Group(groupID, user));
}
else
{
// List of Groups the user belongs to.
queryGroups.addAll(getMemberGroups(user, userDN, groupID));
// List of Groups the user owns;
queryGroups.addAll(getOwnerGroups(user, userDN, groupID));
}
for (Group member : queryGroups)
{
// Require both groupRead and groupWrite
if (member.groupRead != null && member.groupWrite != null)
{
DN groupRead = getGroupDN(member.groupRead.getID());
String groupReadAci =
GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN,
groupRead.toNormalizedString());
DN groupWrite = getGroupDN(member.groupWrite.getID());
String groupWriteAci =
GROUP_WRITE_ACI.replace(ACTUAL_GROUP_TOKEN,
groupWrite.toNormalizedString());
Filter filter = Filter.createANDFilter(
Filter.createEqualityFilter("aci", groupReadAci),
Filter.createEqualityFilter("aci", groupWriteAci));
SearchRequest searchRequest = new SearchRequest(
config.getGroupsDN(), SearchScope.SUB, filter,
new String[] {"cn", "owner", "description",
"modifytimestamp"});
searchRequest.addControl(
new ProxiedAuthorizationV2RequestControl("dn:" +
getSubjectDN().toNormalizedString()));
SearchResult results = getConnection().search(searchRequest);
for (SearchResultEntry result : results.getSearchEntries())
{
String groupName = result.getAttributeValue("cn");
DN ownerDN = result.getAttributeValueAsDN("owner");
User<X500Principal> owner = userPersist.getMember(ownerDN);
// Ignore existing illegal group names.
try
{
Group group = new Group(groupName, owner);
group.description = result.getAttributeValue("description");
group.lastModified =
result.getAttributeValueAsDate("modifytimestamp");
groups.add(group);
}
catch (IllegalArgumentException ignore) { }
}
}
}
return groups;
}
catch (LDAPException e1)
{
// TODO check which LDAP exceptions are transient and which
// ones are
// access control
throw new TransientException("Error getting groups", e1);
}
}
private Group getInactiveGroup(String groupID)
throws UserNotFoundException, GroupNotFoundException, LDAPException
{
Filter filter = Filter.createANDFilter(
Filter.createEqualityFilter("cn", groupID),
Filter.createEqualityFilter("nsaccountlock", "true"));
SearchRequest searchRequest = new SearchRequest(
config.getGroupsDN(), SearchScope.SUB,
filter, new String[] {"cn", "owner"});
searchRequest.addControl(
new ProxiedAuthorizationV2RequestControl("dn:" +
getSubjectDN().toNormalizedString()));
SearchResultEntry searchResult =
getConnection().searchForEntry(searchRequest);
if (searchResult == null)
{
String msg = "Inactive Group not found " + groupID;
logger.debug(msg);
throw new GroupNotFoundException(msg);
}
String groupCN = searchResult.getAttributeValue("cn");
DN groupOwner = searchResult.getAttributeValueAsDN("owner");
User<X500Principal> owner = userPersist.getMember(groupOwner);
return new Group(groupCN, owner);
}
// protected Collection<Group> getRWGroups2(User<T> user, DN userDN,
// String groupID)
// throws TransientException, AccessControlException,
// GroupNotFoundException, UserNotFoundException
// {
// try
// {
// Collection<Group> groups = new ArrayList<Group>();
//
// Collection<Group> queryGroups = new ArrayList<Group>();
// if (groupID != null)
// {
// queryGroups.add(new Group(groupID, user));
// }
// else
// {
// // List of Groups the user belongs to.
// queryGroups.addAll(getMemberGroups(user, userDN, groupID));
//
// // List of Groups the user owns;
// queryGroups.addAll(getOwnerGroups(user, userDN, groupID));
// }
//
// for (Group member : queryGroups)
// {
// // Require both groupRead and groupWrite
// if (member.groupRead != null && member.groupWrite != null)
// {
// DN groupRead = getGroupDN(member.groupRead.getID());
// String groupReadAci =
// GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN,
// groupRead.toNormalizedString());
// DN groupWrite = getGroupDN(member.groupWrite.getID());
// String groupWriteAci =
// GROUP_WRITE_ACI.replace(ACTUAL_GROUP_TOKEN,
// groupWrite.toNormalizedString());
//
// Filter filter = Filter.createANDFilter(
// Filter.createEqualityFilter("aci", groupReadAci),
// Filter.createEqualityFilter("aci", groupWriteAci));
//
// SearchRequest searchRequest = new SearchRequest(
// config.getGroupsDN(), SearchScope.SUB, filter,
// new String[] {"cn", "owner", "description",
// "modifytimestamp"});
//
// searchRequest.addControl(
// new ProxiedAuthorizationV2RequestControl("dn:" +
// getSubjectDN().toNormalizedString()));
//
// SearchResult results = getConnection().search(searchRequest);
// for (SearchResultEntry result : results.getSearchEntries())
// {
// String groupName = result.getAttributeValue("cn");
// DN ownerDN = result.getAttributeValueAsDN("owner");
// User<X500Principal> owner = userPersist.getMember(ownerDN);
//
// // Ignore existing illegal group names.
// try
// {
// Group group = new Group(groupName, owner);
// group.description = result.getAttributeValue("description");
// group.lastModified =
// result.getAttributeValueAsDate("modifytimestamp");
// groups.add(group);
// }
// catch (IllegalArgumentException ignore) { }
// }
// }
// }
// return groups;
// }
// catch (LDAPException e)
// {
// // TODO check which LDAP exceptions are transient and which
// // ones are
// // access control
// throw new TransientException("Error getting groups", e);
// }
// }
/**
* Returns a group based on its LDAP DN. The returned group is bare
......@@ -1019,35 +1034,82 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
* @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"});
// 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;
// }
if (searchResult == null)
/**
*
* @param groupID
* @return
*/
protected DN getGroupDN(final String groupID)
{
try
{
String msg = "Group not found " + groupDN;
logger.debug(msg);
throw new GroupNotFoundException(groupDN.toNormalizedString());
return new DN("cn=" + groupID + "," + config.getGroupsDN());
}
Group group = new Group(searchResult.getAttributeValue("cn"));
group.description = searchResult.getAttributeValue("description");
return group;
catch (LDAPException e)
{
}
throw new IllegalArgumentException(groupID + " not a valid group ID");
}
protected DN getGroupDN(String groupID)
/**
*
* @param groupID
* @return
*/
protected DN getAdminGroupDN(final String groupID)
{
try
{
return new DN("cn=" + groupID + "," + config.getGroupsDN());
return new DN("cn=" + groupID + "," + config.getAdminGroupsDN());
}
catch (LDAPException e)
{
}
throw new IllegalArgumentException(groupID + " not a valid group ID");
}
/**
*
* @param owner
* @return
* @throws UserNotFoundException
*/
protected boolean isCreatorOwner(final User<? extends Principal> owner)
throws UserNotFoundException
{
try
{
User<X500Principal> subjectUser =
userPersist.getMember(getSubjectDN());
if (subjectUser.equals(owner))
{
return true;
}
return false;
}
catch (LDAPException e)
{
throw new RuntimeException(e);
}
}
}
......@@ -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(
......@@ -408,9 +417,9 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
new SearchRequest(this.config.getUsersDN(), SearchScope.SUB,
searchField, new String[] {"entrydn"});
searchRequest.addControl(
new ProxiedAuthorizationV2RequestControl("dn:" +
getSubjectDN().toNormalizedString()));
// searchRequest.addControl(
// new ProxiedAuthorizationV2RequestControl("dn:" +
// getSubjectDN().toNormalizedString()));
SearchResultEntry searchResult =
getConnection().searchForEntry(searchRequest);
......
......@@ -89,10 +89,11 @@ public class LdapDAOTest
static int port = 389;
static String adminDN = "uid=webproxy,ou=WebProxy,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";
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";
LdapConfig config = new LdapConfig(server, port, adminDN, adminPW, userBaseDN, groupBaseDN);
LdapConfig config = new LdapConfig(server, port, adminDN, adminPW, usersDN, groupsDN, adminGroupsDN);
@Test
public void testLdapBindConnection() throws Exception
......
......@@ -69,10 +69,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 userBaseDN = "ou=Users,ou=ds,dc=canfartest,dc=net";
static String groupBaseDN = "ou=Groups,ou=ds,dc=canfartest,dc=net";
//static String userBaseDN = "ou=Users,ou=ds,dc=canfar,dc=net";
//static String groupBaseDN = "ou=Groups,ou=ds,dc=canfar,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 daoTestDN1 = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca";
static String daoTestDN2 = "cn=cadcdaotest2,ou=cadc,o=hia,c=ca";
......@@ -115,7 +116,7 @@ public class LdapGroupDAOTest
anonSubject = new Subject();
anonSubject.getPrincipals().add(unknownUser.getUserID());
config = new LdapConfig(server, port, adminDN, adminPW, userBaseDN, groupBaseDN);
config = new LdapConfig(server, port, adminDN, adminPW, usersDN, groupsDN, adminGroupsDN);
}
LdapGroupDAO<X500Principal> getGroupDAO()
......@@ -158,24 +159,6 @@ public class LdapGroupDAOTest
actualGroup = getGroupDAO().modifyGroup(expectGroup);
assertGroupsEqual(expectGroup, actualGroup);
// groupRead
expectGroup.groupRead = otherGroup;
actualGroup = getGroupDAO().modifyGroup(expectGroup);
assertGroupsEqual(expectGroup, actualGroup);
expectGroup.groupRead = null;
actualGroup = getGroupDAO().modifyGroup(expectGroup);
assertGroupsEqual(expectGroup, actualGroup);
// groupWrite
expectGroup.groupWrite = otherGroup;
actualGroup = getGroupDAO().modifyGroup(expectGroup);
assertGroupsEqual(expectGroup, actualGroup);
expectGroup.groupWrite = null;
actualGroup = getGroupDAO().modifyGroup(expectGroup);
assertGroupsEqual(expectGroup, actualGroup);
// userMembers
expectGroup.getUserMembers().add(daoTestUser2);
actualGroup = getGroupDAO().modifyGroup(expectGroup);
......@@ -196,8 +179,6 @@ public class LdapGroupDAOTest
// delete the group
expectGroup.description = "Happy testing";
expectGroup.groupRead = otherGroup;
expectGroup.groupWrite = otherGroup;
expectGroup.getUserMembers().add(daoTestUser2);
expectGroup.getGroupMembers().add(otherGroup);
......@@ -398,9 +379,9 @@ public class LdapGroupDAOTest
{
getGroupDAO().addGroup(new Group("foo", unknownUser));
fail("addGroup with unknown user should throw " +
"UserNotFoundException");
"AccessControlException");
}
catch (UserNotFoundException ignore) {}
catch (AccessControlException ignore) {}
Group group = getGroupDAO().addGroup(new Group(getGroupID(),
daoTestUser1));
......@@ -476,15 +457,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));
......@@ -651,9 +623,6 @@ public class LdapGroupDAOTest
{
assertTrue(gr2.getUserMembers().contains(user));
}
assertEquals(gr1.groupRead, gr2.groupRead);
assertEquals(gr1.groupWrite, gr2.groupWrite);
assertEquals(gr1.groupWrite, gr2.groupWrite);
assertEquals(gr1.getProperties(), gr2.getProperties());
for (GroupProperty prop : gr1.getProperties())
{
......
......@@ -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
......@@ -96,12 +107,15 @@ public class LdapUserDAOTest
static int port = 389;
static String adminDN = "uid=webproxy,ou=Webproxy,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";
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 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;
......@@ -112,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, userBaseDN, groupBaseDN);
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()
......@@ -138,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;
}
......@@ -149,6 +166,7 @@ public class LdapUserDAOTest
}
}
});
}
/**
......@@ -216,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);
}
}
}
}
}
......@@ -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());
}
}
......@@ -88,21 +88,14 @@ public class Group
// group's group members
private Set<Group> groupMembers = new HashSet<Group>();
public String description;
public Date lastModified;
// group's user admins
private Set<User<? extends Principal>> userAdmins = new HashSet<User<? extends Principal>>();
// Access Control properties
/**
* group that can read details of this group
* Note: this class does not enforce any access control rules
*/
public Group groupRead;
// group's group admins
private Set<Group> groupAdmins = new HashSet<Group>();
/**
* group that can read and write details of this group
* Note: this class does not enforce any access control rules
*/
public Group groupWrite;
public String description;
public Date lastModified;
/**
* Ctor.
......@@ -186,6 +179,24 @@ public class Group
{
return groupMembers;
}
/**
*
* @return individual user admins of this group
*/
public Set<User<? extends Principal>> getUserAdmins()
{
return userAdmins;
}
/**
*
* @return group admins of this group
*/
public Set<Group> getGroupAdmins()
{
return groupAdmins;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
......
......@@ -263,38 +263,37 @@ public class GroupReader
}
// groupRead
Element groupReadElement = groupElement.getChild("groupRead");
if (groupReadElement != null)
// userMembers
Element userMembersElement = groupElement.getChild("userMembers");
if (userMembersElement != null)
{
Element groupReadGroupElement = groupReadElement.getChild("group");
if (groupReadGroupElement != null)
List<Element> userElements = userMembersElement.getChildren("user");
for (Element userMember : userElements)
{
group.groupRead = parseGroup(groupReadGroupElement);
group.getUserMembers().add(UserReader.parseUser(userMember));
}
}
// groupWrite
Element groupWriteElement = groupElement.getChild("groupWrite");
if (groupWriteElement != null)
// groupAdmins
Element groupAdminsElement = groupElement.getChild("groupAdmins");
if (groupAdminsElement != null)
{
Element groupWriteGroupElement = groupWriteElement.getChild("group");
if (groupWriteGroupElement != null)
List<Element> groupElements = groupAdminsElement.getChildren("group");
for (Element groupMember : groupElements)
{
group.groupWrite = parseGroup(groupWriteGroupElement);
group.getGroupAdmins().add(parseGroup(groupMember));
}
}
// userMembers
Element userMembersElement = groupElement.getChild("userMembers");
if (userMembersElement != null)
// userAdmins
Element userAdminsElement = groupElement.getChild("userAdmins");
if (userAdminsElement != null)
{
List<Element> userElements = userMembersElement.getChildren("user");
List<Element> userElements = userAdminsElement.getChildren("user");
for (Element userMember : userElements)
{
group.getUserMembers().add(UserReader.parseUser(userMember));
group.getUserAdmins().add(UserReader.parseUser(userMember));
}
}
......
......@@ -213,22 +213,6 @@ public class GroupWriter
groupElement.addContent(groupMembersElement);
}
// Group groupRead.
if (group.groupRead != null)
{
Element groupReadElement = new Element("groupRead");
groupReadElement.addContent(getGroupElement(group.groupRead, false));
groupElement.addContent(groupReadElement);
}
// Group groupWrite.
if (group.groupWrite != null)
{
Element groupWriteElement = new Element("groupWrite");
groupWriteElement.addContent(getGroupElement(group.groupWrite, false));
groupElement.addContent(groupWriteElement);
}
// Group userMembers
if ((group.getUserMembers() != null) && (!group.getUserMembers().isEmpty()))
{
......@@ -239,6 +223,28 @@ public class GroupWriter
}
groupElement.addContent(userMembersElement);
}
// Group groupAdmins.
if ((group.getGroupAdmins() != null) && (!group.getGroupAdmins().isEmpty()))
{
Element groupAdminsElement = new Element("groupAdmins");
for (Group groupMember : group.getGroupAdmins())
{
groupAdminsElement.addContent(getGroupElement(groupMember, false));
}
groupElement.addContent(groupAdminsElement);
}
// Group userAdmins
if ((group.getUserAdmins() != null) && (!group.getUserAdmins().isEmpty()))
{
Element userAdminsElement = new Element("userAdmins");
for (User<? extends Principal> userMember : group.getUserAdmins())
{
userAdminsElement.addContent(UserWriter.getUserElement(userMember));
}
groupElement.addContent(userAdminsElement);
}
}
return groupElement;
......
......@@ -85,8 +85,8 @@ import org.apache.log4j.Logger;
import org.junit.Test;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.auth.OpenIdPrincipal;
import static org.junit.Assert.assertTrue;
/**
*
......@@ -161,15 +161,15 @@ public class GroupReaderWriterTest
expected.lastModified = new Date();
expected.properties.add(new GroupProperty("key", "value", true));
Group readGroup = new Group("read", new User<Principal>(new X500Principal("cn=foo,o=ca")));
Group writeGroup = new Group("write", new User<Principal>(new NumericPrincipal(123l)));
Group groupMember = new Group("member", new User<Principal>(new OpenIdPrincipal("bar")));
User<Principal> userMember = new User<Principal>(new HttpPrincipal("baz"));
Group groupAdmin = new Group("admin", new User<Principal>(new X500Principal("cn=foo,o=ca")));
User<Principal> userAdmin = new User<Principal>(new HttpPrincipal("admin"));
expected.groupRead = readGroup;
expected.groupWrite = writeGroup;
expected.getGroupMembers().add(groupMember);
expected.getUserMembers().add(userMember);
expected.getGroupAdmins().add(groupAdmin);
expected.getUserAdmins().add(userAdmin);
StringBuilder xml = new StringBuilder();
GroupWriter.write(expected, xml);
......@@ -181,8 +181,6 @@ public class GroupReaderWriterTest
assertEquals(expected.description, actual.description);
assertEquals(expected.lastModified, actual.lastModified);
assertEquals(expected.getProperties(), actual.getProperties());
assertEquals(expected.groupRead, actual.groupRead);
assertEquals(expected.groupWrite, actual.groupWrite);
assertEquals(expected.getGroupMembers(), actual.getGroupMembers());
assertEquals(expected.getUserMembers(), actual.getUserMembers());
}
......
......@@ -115,17 +115,15 @@ public class GroupTest
assertEquals(group3.hashCode(), group4.hashCode());
assertEquals(group3,group4);
group3.description = "Test group";
group4.getUserAdmins().add(user);
assertEquals(group3.hashCode(), group4.hashCode());
assertEquals(group3,group4);
// group read and write equality tests
group3.groupRead = group4;
group3.getGroupAdmins().add(group4);
assertEquals(group3.hashCode(), group4.hashCode());
assertEquals(group3,group4);
// group write equality tests
group3.groupWrite = group4;
group3.description = "Test group";
assertEquals(group3.hashCode(), group4.hashCode());
assertEquals(group3,group4);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment