Skip to content

Commit

Permalink
Enable user groups to be used in XACML processing
Browse files Browse the repository at this point in the history
- Add example policy-set demonstrating group usage

Resolves: https://www.pivotaltracker.com/story/show/73656018
  • Loading branch information
Andrew Woods committed Jun 21, 2014
1 parent 13be72d commit 90b57be
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 2 deletions.
Expand Up @@ -20,10 +20,12 @@
import static org.fcrepo.auth.xacml.URIConstants.ATTRIBUTEID_RESOURCE_ID;
import static org.fcrepo.auth.xacml.URIConstants.ATTRIBUTEID_RESOURCE_WORKSPACE;
import static org.fcrepo.auth.xacml.URIConstants.ATTRIBUTEID_SUBJECT_ID;
import static org.fcrepo.auth.xacml.URIConstants.FCREPO_SUBJECT_GROUP;
import static org.fcrepo.auth.xacml.URIConstants.FCREPO_SUBJECT_ROLE;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -205,4 +207,32 @@ public void addOriginalRequestIP(final String remoteAddr) {
actionList.add(a);
}

/**
* This method adds group attributes to the subject-set.
*
* @param user for arg groups
* @param allGroups to be added to the subject-set
* @return this object
*/
public FedoraEvaluationCtxBuilder addGroups(final Principal user, final Set<Principal> allGroups) {
LOGGER.trace("For user, {}, adding groups {}", user.getName(), allGroups);

if (null == user || null == allGroups || allGroups.isEmpty()) {
LOGGER.trace("Not adding any groups!");
return this;
}

final List<Attribute> subjectAttrs = new ArrayList<>();
for (final Principal group : allGroups) {
// Do not include the user principal in the group attributes.
if (!group.equals(user)) {
final StringAttribute groupAttr = new StringAttribute(group.getName());
final Attribute groupId = new Attribute(FCREPO_SUBJECT_GROUP, null, null, groupAttr);
subjectAttrs.add(groupId);
}
}
this.subjectList.add(new Subject(subjectAttrs));
return this;
}

}
10 changes: 9 additions & 1 deletion src/main/java/org/fcrepo/auth/xacml/URIConstants.java
Expand Up @@ -33,10 +33,18 @@ public abstract class URIConstants {
public static final URI ATTRIBUTEID_SUBJECT_ID = URI
.create(XACMLConstants.ATTRIBUTEID_SUBJECT_ID);

/**
* Roles
*/
public static final String FCREPO_SUBJECT_ROLE_VALUE = "fcrepo-xacml:subject-role";

public static final URI FCREPO_SUBJECT_ROLE = URI.create(FCREPO_SUBJECT_ROLE_VALUE);

/**
* Groups
*/
public static final String FCREPO_SUBJECT_GROUP_VALUE = "fcrepo-xacml:subject-group";
public static final URI FCREPO_SUBJECT_GROUP = URI.create(FCREPO_SUBJECT_GROUP_VALUE);

/**
* ID of the action (ModeShape permission name).
*/
Expand Down
Expand Up @@ -202,6 +202,12 @@ private EvaluationCtx buildEvaluationContext(final Session session,
// add the original IP address
final HttpServletRequest request = (HttpServletRequest) session.getAttribute(FEDORA_SERVLET_REQUEST);
builder.addOriginalRequestIP(request.getRemoteAddr());

// add user's groups
final Set<Principal> allGroups = (Set<Principal>) session.getAttribute(FEDORA_ALL_PRINCIPALS);
LOGGER.debug("effective groups: {}", allGroups);
builder.addGroups(user, allGroups);

return builder.build();
}

Expand Down
Expand Up @@ -25,7 +25,9 @@
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeTemplate;

import com.google.common.collect.ImmutableList;
import org.apache.commons.io.FileUtils;
import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.Datastream;
Expand Down Expand Up @@ -87,7 +89,10 @@ public XACMLWorkspaceInitializer(final File initialPoliciesDirectory, final File
* Initializes node types and default policies.
*/
public void init() {
registerNodeTypes();
// Do not "registerNodeTypes" because the xacml-policy.cnd introduces a cyclical dependency with the main
// fedora-node-types.cnd that causes an exception on repository restart.
// TODO: We can remove this dead code in the near future.
// registerNodeTypes();
loadInitialPolicies();
linkRootToPolicy();
}
Expand All @@ -104,6 +109,18 @@ private void registerNodeTypes() {
LOGGER.debug("registered node type: {}", nt.getName());
}

// Add "authz:xacmlAssignable" mixin to "fedora:resource" type
final NodeType nodeType = mgr.getNodeType("fedora:resource");
final NodeTypeTemplate nodeTypeTemplate = mgr.createNodeTypeTemplate(nodeType);
final String[] superTypes = nodeType.getDeclaredSupertypeNames();
final ImmutableList.Builder<String> listBuilder = ImmutableList.builder();
listBuilder.add(superTypes);
listBuilder.add("authz:xacmlAssignable");
final ImmutableList<String> newSuperTypes = listBuilder.build();
nodeTypeTemplate.setDeclaredSuperTypeNames(newSuperTypes.toArray(new String[newSuperTypes.size()]));

mgr.registerNodeType(nodeTypeTemplate, true);

session.save();
LOGGER.debug("Registered XACML policy node types");
} catch (final RepositoryException | IOException e) {
Expand Down
18 changes: 18 additions & 0 deletions src/main/resources/policies/ReaderGroupPolicySet.xml
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<PolicySet xmlns="urn:oasis:names:tc:xacml:2.0:policy:schema:os"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "urn:oasis:names:tc:xacml:2.0:policy:schema:os http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-policy-schema-os.xsd"
PolicySetId="info:fedora/policies/ReaderGroupPolicySet"
PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:permit-overrides">
<Target>
<Subjects>
<Subject>
<SubjectMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">other</AttributeValue>
<SubjectAttributeDesignator AttributeId="fcrepo-xacml:subject-group" DataType="http://www.w3.org/2001/XMLSchema#string"/>
</SubjectMatch>
</Subject>
</Subjects>
</Target>
<PolicySetIdReference>info:fedora/policies/ReadNormalNodePermissionPolicySet</PolicySetIdReference>
</PolicySet>

0 comments on commit 90b57be

Please sign in to comment.