All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.fedora.server.security.PolicyEnforcementPoint Maven / Gradle / Ivy

Go to download

The Fedora Client is a Java Library that allows API access to a Fedora Repository. The client is typically one part of a full Fedora installation.

The newest version!
/*
 * -----------------------------------------------------------------------------
 *
 * 

License and Copyright: The contents of this file are subject to the * Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of * the License at * http://www.fedora-commons.org/licenses.

* *

Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License.

* *

The entire file consists of original code.

*

Copyright © 2008 Fedora Commons, Inc.
*

Copyright © 2002-2007 The Rector and Visitors of the University of * Virginia and Cornell University
* All rights reserved.

* * ----------------------------------------------------------------------------- */ package fedora.server.security; import java.net.URI; import java.net.URISyntaxException; import java.util.HashSet; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.servlet.ServletContext; import org.apache.log4j.Logger; import com.sun.xacml.attr.StringAttribute; import com.sun.xacml.finder.AttributeFinder; import com.sun.xacml.PDP; import com.sun.xacml.PDPConfig; import com.sun.xacml.ctx.Attribute; import com.sun.xacml.ctx.RequestCtx; import com.sun.xacml.ctx.ResponseCtx; import com.sun.xacml.ctx.Result; import com.sun.xacml.ctx.Subject; import com.sun.xacml.finder.PolicyFinder; import fedora.common.Constants; import fedora.server.Context; import fedora.server.errors.authorization.AuthzDeniedException; import fedora.server.errors.authorization.AuthzException; import fedora.server.errors.authorization.AuthzOperationalException; import fedora.server.errors.authorization.AuthzPermittedException; import fedora.server.storage.DOManager; import fedora.utilities.Log4JRedirectFilter; /** * @author [email protected] */ public class PolicyEnforcementPoint { /** Logger for this class. */ private static final Logger LOG = Logger.getLogger( PolicyEnforcementPoint.class.getName()); public static final String SUBACTION_SEPARATOR = "//"; public static final String SUBRESOURCE_SEPARATOR = "//"; private static PolicyEnforcementPoint singleton = null; private static int count = 0; private String enforceMode = ENFORCE_MODE_ENFORCE_POLICIES; static final String ENFORCE_MODE_ENFORCE_POLICIES = "enforce-policies"; static final String ENFORCE_MODE_PERMIT_ALL_REQUESTS = "permit-all-requests"; static final String ENFORCE_MODE_DENY_ALL_REQUESTS = "deny-all-requests"; public static final String XACML_SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id"; public static final String XACML_ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id"; public static final String XACML_RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id"; private final URI XACML_SUBJECT_ID_URI; private final URI XACML_ACTION_ID_URI; private final URI XACML_RESOURCE_ID_URI; private final URI SUBJECT_ID_URI; private final URI ACTION_ID_URI; private final URI ACTION_API_URI; private final URI ACTION_CONTEXT_URI; private final URI RESOURCE_ID_URI; private final URI RESOURCE_NAMESPACE_URI; static { // force com.sun.xacml logging to use Log4J Log4JRedirectFilter.apply("com.sun.xacml.finder.AttributeFinder"); } private PolicyEnforcementPoint() { URI xacmlSubjectIdUri = null; URI xacmlActionIdUri = null; URI xacmlResourceIdUri = null; URI subjectIdUri = null; URI actionIdUri = null; URI actionApiUri = null; URI contextUri = null; URI pidUri = null; URI namespaceUri = null; try { xacmlSubjectIdUri = new URI(XACML_SUBJECT_ID); xacmlActionIdUri = new URI(XACML_ACTION_ID); xacmlResourceIdUri = new URI(XACML_RESOURCE_ID); subjectIdUri = new URI(Constants.SUBJECT.LOGIN_ID.uri); actionIdUri = new URI(Constants.ACTION.ID.uri); actionApiUri = new URI(Constants.ACTION.API.uri); contextUri = new URI(Constants.ACTION.CONTEXT_ID.uri); pidUri = new URI(Constants.OBJECT.PID.uri); namespaceUri = new URI(Constants.OBJECT.NAMESPACE.uri); } catch (URISyntaxException e) { LOG.fatal("Bad URI syntax", e); } finally { XACML_SUBJECT_ID_URI = xacmlSubjectIdUri; XACML_ACTION_ID_URI = xacmlActionIdUri; XACML_RESOURCE_ID_URI = xacmlResourceIdUri; SUBJECT_ID_URI = subjectIdUri; ACTION_ID_URI = actionIdUri; ACTION_API_URI = actionApiUri; ACTION_CONTEXT_URI = contextUri; RESOURCE_ID_URI = pidUri; RESOURCE_NAMESPACE_URI = namespaceUri; } } public static final PolicyEnforcementPoint getInstance() { if (singleton == null) { singleton = new PolicyEnforcementPoint(); } count++; LOG.debug ("***another use (" + count + ") of XACMLPep singleton"); return singleton; } /** * xacml pdp */ private PDP pdp = null; /** * available during init(); keep as logging hook */ private ServletContext servletContext = null; private ContextAttributeFinderModule contextAttributeFinder; public final void newPdp() throws Exception { AttributeFinder attrFinder = new AttributeFinder(); List attrModules = new ArrayList(); ResourceAttributeFinderModule resourceAttributeFinder = ResourceAttributeFinderModule.getInstance(); resourceAttributeFinder.setServletContext(servletContext); resourceAttributeFinder.setDOManager(manager); resourceAttributeFinder.setOwnerIdSeparator(this.ownerIdSeparator); attrModules.add(resourceAttributeFinder); try { LOG.debug("about to set contextAttributeFinder in original"); contextAttributeFinder = ContextAttributeFinderModule.getInstance(); } catch(Throwable t) { this.enforceMode = ENFORCE_MODE_DENY_ALL_REQUESTS; LOG.error("Error in newPdp", t); if (t instanceof Exception) { throw (Exception) t; } throw new Exception("wrapped",t); } LOG.debug("just set contextAttributeFinder=" + contextAttributeFinder); contextAttributeFinder.setServletContext(servletContext); attrModules.add(contextAttributeFinder); attrFinder.setModules(attrModules); LOG.debug("before building policy finder"); PolicyFinder policyFinder = new PolicyFinder(); LOG.debug("just constructed policy finder"); Set policyModules = new HashSet(); LOG.debug("just constructed policy module hashset"); PolicyFinderModule combinedPolicyModule = null; LOG.debug("***before constucting fedora policy finder module, policySchemaPath = " + policySchemaPath); combinedPolicyModule = new PolicyFinderModule(combiningAlgorithm, globalPolicyConfig, globalBackendPolicyConfig, globalPolicyGuiToolConfig, manager, validateRepositoryPolicies, validateObjectPoliciesFromDatastream, policySchemaPath); LOG.debug("after constucting fedora policy finder module"); LOG.debug("before adding fedora policy finder module to policy finder hashset"); policyModules.add(combinedPolicyModule); LOG.debug("after adding fedora policy finder module to policy finder hashset"); LOG.debug("o before setting policy finder hashset into policy finder"); policyFinder.setModules(policyModules); LOG.debug("o after setting policy finder hashset into policy finder"); PDP pdp = null; LOG.debug(combinedPolicyModule.getLoadErrors() + " load errors"); if (combinedPolicyModule.getLoadErrors() == 0) { LOG.debug("0 class errors"); pdp = new PDP(new PDPConfig(attrFinder, policyFinder, null)); } if (pdp == null) { LOG.debug("null pdp"); Exception se = new Exception("Xaclmpep.init() failed: no pdp"); throw se; } synchronized (this) { this.pdp = pdp; //so enforce() will wait, if this pdp update is in progress } } String combiningAlgorithm = null; String globalPolicyConfig = null; String globalBackendPolicyConfig = null; String globalPolicyGuiToolConfig = null; DOManager manager = null; boolean validateRepositoryPolicies = false; boolean validateObjectPoliciesFromDatastream = false; String policySchemaPath = null; String ownerIdSeparator = ","; public void initPep(String enforceMode, String combiningAlgorithm, String globalPolicyConfig, String globalBackendPolicyConfig, String globalPolicyGuiToolConfig, DOManager manager, boolean validateRepositoryPolicies, boolean validateObjectPoliciesFromDatastream, String policySchemaPath, String ownerIdSeparator ) throws Exception { LOG.debug("in initPep()"); destroy(); this.enforceMode = enforceMode; if (ENFORCE_MODE_ENFORCE_POLICIES.equals(enforceMode)) { } else if (ENFORCE_MODE_PERMIT_ALL_REQUESTS.equals(enforceMode)) { } else if (ENFORCE_MODE_DENY_ALL_REQUESTS.equals(enforceMode)) { } else { throw new AuthzOperationalException("invalid enforceMode from config"); } this.combiningAlgorithm = combiningAlgorithm; this.globalPolicyConfig = globalPolicyConfig; this.globalBackendPolicyConfig = globalBackendPolicyConfig; this.globalPolicyGuiToolConfig = globalPolicyGuiToolConfig; this.manager = manager; this.validateRepositoryPolicies = validateRepositoryPolicies; this.validateObjectPoliciesFromDatastream = validateObjectPoliciesFromDatastream; this.policySchemaPath = policySchemaPath; this.ownerIdSeparator = ownerIdSeparator; LOG.debug("***in initPep(), before calling newPdp()"); newPdp(); LOG.debug("***exiting initPep()"); } public void inactivate() { destroy(); } public void destroy() { servletContext = null; pdp = null; } private final Set wrapSubjects(String subjectLoginId) { LOG.debug("wrapSubjectIdAsSubjects(): " + subjectLoginId); StringAttribute stringAttribute = new StringAttribute(""); Attribute subjectAttribute = new Attribute(XACML_SUBJECT_ID_URI, null, null, stringAttribute); LOG.debug("wrapSubjectIdAsSubjects(): subjectAttribute, id=" + subjectAttribute.getId() + ", type=" + subjectAttribute.getType() + ", value=" + subjectAttribute.getValue()); Set subjectAttributes = new HashSet(); subjectAttributes.add(subjectAttribute); if ((subjectLoginId != null) && ! "".equals(subjectLoginId)) { stringAttribute = new StringAttribute(subjectLoginId); subjectAttribute = new Attribute(SUBJECT_ID_URI, null, null, stringAttribute); LOG.debug("wrapSubjectIdAsSubjects(): subjectAttribute, id=" + subjectAttribute.getId() + ", type=" + subjectAttribute.getType() + ", value=" + subjectAttribute.getValue()); } subjectAttributes.add(subjectAttribute); Subject singleSubject = new Subject(subjectAttributes); Set subjects = new HashSet(); subjects.add(singleSubject); return subjects; } private final Set wrapActions(String actionId, String actionApi, String contextIndex) { Set actions = new HashSet(); Attribute action = new Attribute(XACML_ACTION_ID_URI, null, null, new StringAttribute("")); actions.add(action); action = new Attribute(ACTION_ID_URI, null, null, new StringAttribute(actionId)); actions.add(action); action = new Attribute(ACTION_API_URI, null, null, new StringAttribute(actionApi)); actions.add(action); action = new Attribute(ACTION_CONTEXT_URI, null, null, new StringAttribute(contextIndex)); actions.add(action); return actions; } private final Set wrapResources(String pid, String namespace) throws AuthzOperationalException { Set resources = new HashSet(); Attribute attribute = null; attribute = new Attribute(XACML_RESOURCE_ID_URI, null, null, new StringAttribute("")); resources.add(attribute); attribute = new Attribute(RESOURCE_ID_URI, null, null, new StringAttribute(pid)); resources.add(attribute); attribute = new Attribute(RESOURCE_NAMESPACE_URI, null, null, new StringAttribute(namespace)); resources.add(attribute); return resources; } private int n = 0; private synchronized int next() { return n++; } private final Set NULL_SET = new HashSet(); public final void enforce(String subjectId, String action, String api, String pid, String namespace, Context context) throws AuthzException { long enforceStartTime = System.currentTimeMillis(); try { synchronized (this) { //wait, if pdp update is in progress } if (ENFORCE_MODE_PERMIT_ALL_REQUESTS.equals(enforceMode)) { LOG.debug("permitting request because enforceMode==ENFORCE_MODE_PERMIT_ALL_REQUESTS"); } else if (ENFORCE_MODE_DENY_ALL_REQUESTS.equals(enforceMode)) { LOG.debug("denying request because enforceMode==ENFORCE_MODE_DENY_ALL_REQUESTS"); throw new AuthzDeniedException("all requests are currently denied"); } else if (! ENFORCE_MODE_ENFORCE_POLICIES.equals(enforceMode)) { LOG.debug("denying request because enforceMode is invalid"); throw new AuthzOperationalException("invalid enforceMode from config"); } else { ResponseCtx response = null; String contextIndex = null; try { contextIndex = (new Integer(next())).toString(); LOG.debug("context index set=" + contextIndex); Set subjects = wrapSubjects(subjectId); Set actions = wrapActions(action, api, contextIndex); Set resources = wrapResources(pid, namespace); RequestCtx request = new RequestCtx(subjects, resources, actions, NULL_SET); Set tempset = request.getAction(); Iterator tempit = tempset.iterator(); while (tempit.hasNext()) { Attribute tempobj = (Attribute) tempit.next(); LOG.debug("request action has " + tempobj.getId() + "=" + tempobj.getValue().toString()); } LOG.debug("about to ref contextAttributeFinder=" + contextAttributeFinder); contextAttributeFinder.registerContext(contextIndex, context); long st = System.currentTimeMillis(); try { response = pdp.evaluate(request); } finally { long dur = System.currentTimeMillis() - st; LOG.debug("Policy evaluation took " + dur + "ms."); } LOG.debug("in pep, after evaluate() called"); } catch (Throwable t) { LOG.error("Error evaluating policy", t); throw new AuthzOperationalException(""); } finally { contextAttributeFinder.unregisterContext(contextIndex); } LOG.debug("in pep, before denyBiasedAuthz() called"); if (! denyBiasedAuthz(response.getResults())) { throw new AuthzDeniedException(""); } } if (context.getNoOp()) { throw new AuthzPermittedException("noOp"); } } finally { long dur = System.currentTimeMillis() - enforceStartTime; LOG.debug("Policy enforcement took " + dur + "ms."); } } private static final boolean denyBiasedAuthz(Set set) { int nPermits = 0; //explicit permit returned int nDenies = 0; //explicit deny returned int nNotApplicables = 0; //no targets matched int nIndeterminates = 0; //for targets matched, no rules matched int nWrongs = 0; //none of the above, i.e., unreported failure, should not happen Iterator it = set.iterator(); int which = 0; while (it.hasNext()) { Result result = (Result) it.next(); int decision = result.getDecision(); switch (decision) { case Result.DECISION_PERMIT: nPermits++; break; case Result.DECISION_DENY: nDenies++; break; case Result.DECISION_INDETERMINATE: nIndeterminates++; break; case Result.DECISION_NOT_APPLICABLE: nNotApplicables++; break; default: nWrongs++; break; } } LOG.debug("AUTHZ: permits=" + nPermits + " denies=" + nDenies + " indeterminates=" + nIndeterminates + " notApplicables=" + nNotApplicables + " unexpecteds=" + nWrongs); return (nPermits >= 1) && (nDenies == 0) && (nIndeterminates == 0) && (nWrongs == 0); // don't care about NotApplicables } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy