Skip to content

Commit

Permalink
Update fcrepo-module-auth-xacml due to upstream changes.
Browse files Browse the repository at this point in the history
- Add logging
- Update spring XML
- Change classes where implementations have been replaced

Partial resolution of: https://www.pivotaltracker.com/story/show/80568076
  • Loading branch information
Andrew Woods committed Oct 21, 2014
1 parent 48dc383 commit 2bc5a2e
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 48 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Expand Up @@ -158,6 +158,11 @@
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

Expand Down
48 changes: 36 additions & 12 deletions src/main/java/org/fcrepo/auth/xacml/FedoraPolicyFinderModule.java
Expand Up @@ -29,10 +29,11 @@
import javax.xml.parsers.DocumentBuilderFactory;

import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.Datastream;
import org.fcrepo.jcr.FedoraJcrTypes;
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.services.DatastreamService;
import org.fcrepo.kernel.services.BinaryService;
import org.fcrepo.kernel.services.NodeService;
import org.jboss.security.xacml.sunxacml.AbstractPolicy;
import org.jboss.security.xacml.sunxacml.EvaluationCtx;
Expand Down Expand Up @@ -68,7 +69,7 @@ public class FedoraPolicyFinderModule extends PolicyFinderModule {
private SessionFactory sessionFactory;

@Autowired
private DatastreamService datastreamService;
private BinaryService binaryService;

@Autowired
private NodeService nodeService;
Expand Down Expand Up @@ -98,11 +99,11 @@ public final boolean isIdReferenceSupported() {
/**
* Retrieves the policy from the given policy node
*
* @param policyDatastream
* @param policyBinary
* @return
*/
private AbstractPolicy getPolicy(final Datastream policyDatastream) {
return loadPolicy(policyDatastream.getBinary());
private AbstractPolicy getPolicy(final FedoraBinary policyBinary) {
return loadPolicy(policyBinary);
}

/**
Expand Down Expand Up @@ -160,6 +161,8 @@ public final PolicyFinderResult findPolicy(final EvaluationCtx context) {
final AttributeValue resourceIdAttValue = ridEvalRes.getAttributeValue();
String path = resourceIdAttValue.getValue().toString();

LOGGER.debug("Finding policy for resource: {}", path);

if ("".equals(path.trim())) {
path = "/";
}
Expand All @@ -175,17 +178,28 @@ public final PolicyFinderResult findPolicy(final EvaluationCtx context) {

// This should never happen, as PolicyUtil.getFirstRealNode() at least returns the root node.
if (null == nodeWithPolicy) {
LOGGER.warn("No policy found for: {}!", path);
return new PolicyFinderResult();
}

final Property prop = nodeWithPolicy.getProperty(XACML_POLICY_PROPERTY);
final Datastream policyDatastream = datastreamService.asDatastream(prop.getNode());

if (policyDatastream == null) {
final FedoraBinary policyBinary;
final FedoraResource resource = nodeService.getObject(internalSession, prop.getNode().getPath());
if (resource.hasType(FedoraJcrTypes.FEDORA_DATASTREAM)) {
policyBinary = binaryService.findOrCreateBinary(internalSession, resource.getNode().getPath());

} else {
LOGGER.warn("Policy Binary not found for: {}", path);
return new PolicyFinderResult();
}

if (policyBinary == null) {
LOGGER.warn("Policy binary for path: {} was null!", nodeWithPolicy.getPath());
return new PolicyFinderResult();
}

final AbstractPolicy policy = getPolicy(policyDatastream);
final AbstractPolicy policy = getPolicy(policyBinary);

// Evaluate if the policy targets match the current context
final MatchResult match = policy.match(context);
Expand Down Expand Up @@ -228,12 +242,22 @@ public final PolicyFinderResult findPolicy(final URI idReference,

final String path = PolicyUtil.getPathForId(id);
final Session internalSession = sessionFactory.getInternalSession();
final Datastream policyDatastream = datastreamService.findOrCreateDatastream(internalSession, path);
final AbstractPolicy policy = getPolicy(policyDatastream);

final FedoraBinary policyBinary;
final FedoraResource resource = nodeService.getObject(internalSession, path);
if (resource.hasType(FedoraJcrTypes.FEDORA_DATASTREAM)) {
policyBinary = binaryService.findOrCreateBinary(internalSession, resource.getNode().getPath());

} else {
LOGGER.warn("Policy Binary not found for: {}", path);
return new PolicyFinderResult();
}

final AbstractPolicy policy = getPolicy(policyBinary);

return new PolicyFinderResult(policy);

} catch (final RepositoryRuntimeException e) {
} catch (final RepositoryRuntimeException | RepositoryException e) {
LOGGER.warn("Failed to retrieve a policy for " + idReference.toString(), e);
return new PolicyFinderResult();
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/fcrepo/auth/xacml/PolicyUtil.java
Expand Up @@ -30,6 +30,8 @@
import org.jboss.security.xacml.sunxacml.EvaluationCtx;
import org.jboss.security.xacml.sunxacml.attr.AttributeValue;
import org.jboss.security.xacml.sunxacml.cond.EvaluationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

Expand All @@ -39,6 +41,8 @@
*/
public class PolicyUtil {

private static final Logger LOGGER = LoggerFactory.getLogger(PolicyUtil.class);

private PolicyUtil() {
//not called
}
Expand Down Expand Up @@ -109,6 +113,8 @@ public static String getPathForId(final String id) {
* @return a Node in session
*/
public static Node getFirstRealNode(final String modepath, final Session session) {
LOGGER.debug("Finding firstRealNode for path: {}", modepath);

Node node = null;
for (String path = modepath; path.contains("/{"); path = path.substring(0, path.lastIndexOf("/{"))) {
try {
Expand All @@ -126,6 +132,8 @@ public static Node getFirstRealNode(final String modepath, final Session session
throw new Error("Cannot reach repository", e);
}
}

LOGGER.debug("Found firstRealNode for path: {}", modepath);
return node;
}

Expand Down
Expand Up @@ -28,14 +28,13 @@
import java.util.Iterator;
import java.util.Set;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.rdf.impl.PropertiesRdfContext;
import org.fcrepo.kernel.rdf.IdentifierTranslator;
import org.fcrepo.kernel.impl.rdf.impl.DefaultIdentifierTranslator;
import org.fcrepo.kernel.services.NodeService;

Expand Down Expand Up @@ -69,7 +68,7 @@ public class TripleAttributeFinderModule extends AttributeFinderModule {

private static BagAttribute empty_bag;

private static IdentifierTranslator idTranslator;
private static IdentifierConverter<Resource, FedoraResource> idTranslator;

/**
* Fedora's ModeShape session factory.
Expand Down Expand Up @@ -158,8 +157,12 @@ public final EvaluationResult findAttribute(final URI attributeType,
// if dealing with set_property action, use parent node for triples
final Set<String> actions = PolicyUtil.getActions(context);
if (actions.contains("set_property") || actions.contains("add_node")) {
resourceId = resourceId.substring(0, resourceId.lastIndexOf("/{"));
if (resourceId.length() == 0) {
final int index = resourceId.lastIndexOf("/{");
if (index > -1) {
resourceId = resourceId.substring(0, index);
}

if (resourceId.isEmpty()) {
resourceId = "/";
}
}
Expand All @@ -174,7 +177,7 @@ public final EvaluationResult findAttribute(final URI attributeType,
return new EvaluationResult(empty_bag);
}
path = resource.getPath();
idTranslator = new DefaultIdentifierTranslator();
idTranslator = new DefaultIdentifierTranslator(session);

} catch (final RepositoryRuntimeException e) {
// If the object does not exist, it may be due to the action being "create"
Expand All @@ -196,11 +199,9 @@ public final EvaluationResult findAttribute(final URI attributeType,
return new EvaluationResult(status);
}

Resource graphNode;
try {
graphNode = idTranslator.getSubject(resource.getPath());
} catch (final RepositoryException e) {
LOGGER.debug("Cannot get subject for[{}]: {}", resource.getPath(), e);
final Resource graphNode = idTranslator.reverse().convert(resource);
if (null == graphNode) {
LOGGER.debug("Cannot get subject for[{}]", resource.getPath());
final Status status =
new Status(singletonList(STATUS_PROCESSING_ERROR),
"Error retrieving properties for [" + path + "]!");
Expand Down
Expand Up @@ -148,6 +148,12 @@ public boolean rolesHavePermission(final Session session,
break;
}
}

LOGGER.debug("Request for actions: {}, on path: {}, with roles: {}. Permission={}",
actions,
absPath,
roles,
permit);
return permit;
}

Expand Down
Expand Up @@ -32,7 +32,7 @@
import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.services.DatastreamService;
import org.fcrepo.kernel.services.BinaryService;
import org.modeshape.jcr.api.nodetype.NodeTypeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -57,7 +57,7 @@ public class XACMLWorkspaceInitializer {
private SessionFactory sessionFactory;

@Autowired
private DatastreamService datastreamService;
private BinaryService binaryService;

private File initialPoliciesDirectory;

Expand Down Expand Up @@ -154,12 +154,12 @@ private void loadInitialPolicies() {
for (final File p : initialPoliciesDirectory.listFiles()) {
final String id = PolicyUtil.getID(FileUtils.openInputStream(p));
final String repoPath = PolicyUtil.getPathForId(id);
final FedoraBinary binary = datastreamService.getBinary(session, repoPath);
final FedoraBinary binary = binaryService.findOrCreateBinary(session, repoPath);
binary.setContent(new FileInputStream(p),
"application/xml",
null,
p.getName(),
datastreamService.getStoragePolicyDecisionPoint());
null);

LOGGER.info("Add initial policy {} at {}", p.getAbsolutePath(), binary.getPath());
}
Expand Down
Expand Up @@ -39,9 +39,11 @@
import javax.jcr.Session;

import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.jcr.FedoraJcrTypes;
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.services.DatastreamService;
import org.fcrepo.kernel.services.BinaryService;
import org.fcrepo.kernel.services.NodeService;
import org.jboss.security.xacml.sunxacml.EvaluationCtx;
import org.jboss.security.xacml.sunxacml.PolicyReference;
import org.jboss.security.xacml.sunxacml.attr.AttributeValue;
Expand Down Expand Up @@ -80,11 +82,17 @@ public class FedoraPolicyFinderModuleTest {
@Mock
private Datastream mockPolicyDs;

@Mock
private Datastream mockResource;

@Mock
private FedoraBinary mockBinary;

@Mock
private DatastreamService mockDsService;
private NodeService mockNodeService;

@Mock
private BinaryService mockBinaryService;

@Mock
private PolicyFinder mockFinder;
Expand Down Expand Up @@ -114,11 +122,18 @@ public void setUp() throws Exception {

when(mockPolicyProperty.getNode()).thenReturn(mockPolicyNode);

when(mockDsService.asDatastream(mockPolicyNode)).thenReturn(mockPolicyDs);
when(mockNodeService.getObject(any(Session.class), anyString())).thenReturn(mockResource);
when(mockResource.hasType(FedoraJcrTypes.FEDORA_DATASTREAM)).thenReturn(true);
when(mockResource.getBinary()).thenReturn(mockBinary);

when(mockResource.getNode()).thenReturn(mockNode);
when(mockNode.getPath()).thenReturn("/{}myPath");
when(mockBinaryService.findOrCreateBinary(any(Session.class), anyString())).thenReturn(mockBinary);

finderModule = new FedoraPolicyFinderModule();
setField(finderModule, "sessionFactory", mockSessionFactory);
setField(finderModule, "datastreamService", mockDsService);
setField(finderModule, "nodeService", mockNodeService);
setField(finderModule, "binaryService", mockBinaryService);
finderModule.init(mockFinder);
}

Expand Down Expand Up @@ -163,7 +178,6 @@ public void testFindPolicyByIdReference() throws Exception {

when(mockPolicyDs.getBinary()).thenReturn(mockBinary);
when(mockBinary.getContent()).thenReturn(this.getClass().getResourceAsStream("/xacml/testPolicy.xml"));
when(mockDsService.findOrCreateDatastream(any(Session.class), eq(policyPath))).thenReturn(mockPolicyDs);

final PolicyFinderResult result = finderModule.findPolicy(idReference, 0, null, null);

Expand All @@ -188,7 +202,6 @@ public void testFindPolicySet() throws Exception {
when(referencedPolicyDs.getBinary()).thenReturn(referencedPolicyBinary);
when(referencedPolicyBinary.getContent()).thenReturn(
this.getClass().getResourceAsStream("/xacml/adminPermissionPolicySet.xml"));
when(mockDsService.findOrCreateDatastream(any(Session.class), eq(referencedId))).thenReturn(referencedPolicyDs);

final FedoraEvaluationCtxBuilder ctxBuilder = new FedoraEvaluationCtxBuilder();
ctxBuilder.addResourceID("/{}myPath");
Expand Down
Expand Up @@ -37,8 +37,8 @@
import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.rdf.impl.PropertiesRdfContext;
import org.fcrepo.kernel.rdf.IdentifierTranslator;
import org.fcrepo.kernel.services.NodeService;
import org.fcrepo.kernel.utils.iterators.RdfStream;

Expand Down Expand Up @@ -80,7 +80,7 @@ public class TripleAttributeFinderModuleTest {
private FedoraResource mockFedoraResource;

@Mock
private IdentifierTranslator mockIdentifierTranslator;
private IdentifierConverter mockIdentifierTranslator;

@Mock
private Model mockModel;
Expand Down Expand Up @@ -165,9 +165,10 @@ public void testFindAttribute() throws RepositoryException {
final String resourceId = "/{ns}path/{ns}to/{ns}resource";

when(mockNodeService.getObject(mockSession, resourceId)).thenReturn(mockFedoraResource);
when(mockFedoraResource.getTriples(any(IdentifierTranslator.class), eq(PropertiesRdfContext.class))).thenReturn(
when(mockFedoraResource.getTriples(any(IdentifierConverter.class), eq(PropertiesRdfContext.class))).thenReturn(
mockRdfStream);
when(mockIdentifierTranslator.getSubject(any(String.class))).thenReturn(mockResource);
when(mockIdentifierTranslator.reverse()).thenReturn(mockIdentifierTranslator);
when(mockIdentifierTranslator.convert(mockFedoraResource)).thenReturn(mockResource);
when(mockFedoraResource.getPath()).thenReturn(resourceId);
when(mockRdfStream.asModel()).thenReturn(mockModel);
when(mockModel.listObjectsOfProperty(any(Resource.class),
Expand Down Expand Up @@ -300,7 +301,7 @@ public void testFindAttributeBadProperties() throws RepositoryException {
final String[] actions = { "read" };

when(mockNodeService.getObject(mockSession, resourceId)).thenReturn(mockFedoraResource);
when(mockFedoraResource.getTriples(any(IdentifierTranslator.class), eq(PropertiesRdfContext.class))).thenThrow(
when(mockFedoraResource.getTriples(any(IdentifierConverter.class), eq(PropertiesRdfContext.class))).thenThrow(
new RepositoryRuntimeException("expected"));

final EvaluationResult result = doFindAttribute(resourceId, actions);
Expand Down

0 comments on commit 2bc5a2e

Please sign in to comment.