Commit c37e69c9 authored by cdanger's avatar cdanger

Added unit tests for issue OW2 #23

parent 8499efca
......@@ -24,6 +24,11 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XdmNode;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attributes;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.BaseRequestFilter;
import org.ow2.authzforce.core.pdp.api.ImmutableIndividualDecisionRequest;
......@@ -38,11 +43,6 @@ import org.ow2.authzforce.core.pdp.api.value.DatatypeFactoryRegistry;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XdmNode;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attributes;
/**
* Default Request filter for Individual Decision Requests only (no support of Multiple Decision Profile in particular)
*
......@@ -52,8 +52,8 @@ public final class DefaultRequestFilter extends BaseRequestFilter
{
/**
*
* Factory for this type of request filter that allows duplicate <Attribute> with same meta-data in the same
* <Attributes> element of a Request (complying with XACML 3.0 core spec, §7.3.3).
* Factory for this type of request filter that allows duplicate <Attribute> with same meta-data in the same <Attributes> element of a Request (complying with XACML 3.0 core spec,
* §7.3.3).
*
*/
public static final class LaxFilterFactory implements RequestFilter.Factory
......@@ -70,12 +70,10 @@ public final class DefaultRequestFilter extends BaseRequestFilter
}
@Override
public RequestFilter getInstance(final DatatypeFactoryRegistry datatypeFactoryRegistry,
final boolean strictAttributeIssuerMatch, final boolean requireContentForXPath,
public RequestFilter getInstance(final DatatypeFactoryRegistry datatypeFactoryRegistry, final boolean strictAttributeIssuerMatch, final boolean requireContentForXPath,
final Processor xmlProcessor)
{
return new DefaultRequestFilter(datatypeFactoryRegistry, strictAttributeIssuerMatch, true,
requireContentForXPath, xmlProcessor);
return new DefaultRequestFilter(datatypeFactoryRegistry, strictAttributeIssuerMatch, true, requireContentForXPath, xmlProcessor);
}
/**
......@@ -87,8 +85,8 @@ public final class DefaultRequestFilter extends BaseRequestFilter
/**
*
* Factory for this type of request filter that does NOT allow duplicate <Attribute> with same meta-data in
* the same <Attributes> element of a Request (NOT complying fully with XACML 3.0 core spec, §7.3.3).
* Factory for this type of request filter that does NOT allow duplicate <Attribute> with same meta-data in the same <Attributes> element of a Request (NOT complying fully with XACML
* 3.0 core spec, §7.3.3).
*
*/
public static final class StrictFilterFactory implements RequestFilter.Factory
......@@ -102,63 +100,54 @@ public final class DefaultRequestFilter extends BaseRequestFilter
}
@Override
public RequestFilter getInstance(final DatatypeFactoryRegistry datatypeFactoryRegistry,
final boolean strictAttributeIssuerMatch, final boolean requireContentForXPath,
public RequestFilter getInstance(final DatatypeFactoryRegistry datatypeFactoryRegistry, final boolean strictAttributeIssuerMatch, final boolean requireContentForXPath,
final Processor xmlProcessor)
{
return new DefaultRequestFilter(datatypeFactoryRegistry, strictAttributeIssuerMatch, false,
requireContentForXPath, xmlProcessor);
return new DefaultRequestFilter(datatypeFactoryRegistry, strictAttributeIssuerMatch, false, requireContentForXPath, xmlProcessor);
}
}
private DefaultRequestFilter(final DatatypeFactoryRegistry datatypeFactoryRegistry,
final boolean strictAttributeIssuerMatch, final boolean allowAttributeDuplicates,
private DefaultRequestFilter(final DatatypeFactoryRegistry datatypeFactoryRegistry, final boolean strictAttributeIssuerMatch, final boolean allowAttributeDuplicates,
final boolean requireContentForXPath, final Processor xmlProcessor)
{
super(datatypeFactoryRegistry, strictAttributeIssuerMatch, allowAttributeDuplicates, requireContentForXPath,
xmlProcessor);
super(datatypeFactoryRegistry, strictAttributeIssuerMatch, allowAttributeDuplicates, requireContentForXPath, xmlProcessor);
}
/** {@inheritDoc} */
@Override
public List<? extends IndividualDecisionRequest> filter(final List<Attributes> attributesList,
final JaxbXACMLAttributesParser xacmlAttrsParser, final boolean isApplicablePolicyIdListReturned,
final boolean combinedDecision, final XPathCompiler xPathCompiler,
final Map<String, String> namespaceURIsByPrefix) throws IndeterminateEvaluationException
public List<? extends IndividualDecisionRequest> filter(final List<Attributes> attributesList, final JaxbXACMLAttributesParser xacmlAttrsParser, final boolean isApplicablePolicyIdListReturned,
final boolean combinedDecision, final XPathCompiler xPathCompiler, final Map<String, String> namespaceURIsByPrefix) throws IndeterminateEvaluationException
{
final Map<AttributeGUID, Bag<?>> namedAttributes = HashObjObjMaps.newUpdatableMap(attributesList.size());
final Map<String, XdmNode> extraContentsByCategory = HashObjObjMaps.newUpdatableMap(attributesList.size());
final List<Attributes> attributesToIncludeInResult = new ArrayList<>();
/*
* attributesToIncludeInResult.size() <= attributesList.size()
*/
final List<Attributes> attributesToIncludeInResult = new ArrayList<>(attributesList.size());
for (final Attributes jaxbAttributes : attributesList)
{
final String categoryName = jaxbAttributes.getCategory();
final SingleCategoryAttributes<?> categorySpecificAttributes = xacmlAttrsParser
.parseAttributes(jaxbAttributes, xPathCompiler);
final SingleCategoryAttributes<?> categorySpecificAttributes = xacmlAttrsParser.parseAttributes(jaxbAttributes, xPathCompiler);
if (categorySpecificAttributes == null)
{
// skip this empty Attributes
continue;
}
final XdmNode oldVal = extraContentsByCategory.put(categoryName,
categorySpecificAttributes.getExtraContent());
final XdmNode oldVal = extraContentsByCategory.put(categoryName, categorySpecificAttributes.getExtraContent());
/*
* No support for Multiple Decision Profile -> no support for repeated categories as specified in Multiple
* Decision Profile. So we must check duplicate attribute categories.
* No support for Multiple Decision Profile -> no support for repeated categories as specified in Multiple Decision Profile. So we must check duplicate attribute categories.
*/
if (oldVal != null)
{
throw new IndeterminateEvaluationException(
"Unsupported repetition of Attributes[@Category='" + categoryName
+ "'] (feature 'urn:oasis:names:tc:xacml:3.0:profile:multiple:repeated-attribute-categories' is not supported)",
StatusHelper.STATUS_SYNTAX_ERROR);
throw new IndeterminateEvaluationException("Unsupported repetition of Attributes[@Category='" + categoryName
+ "'] (feature 'urn:oasis:names:tc:xacml:3.0:profile:multiple:repeated-attribute-categories' is not supported)", StatusHelper.STATUS_SYNTAX_ERROR);
}
/*
* Convert growable (therefore mutable) bag of attribute values to immutable ones. Indeed, we must guarantee
* that attribute values remain constant during the evaluation of the request, as mandated by the XACML
* spec, section 7.3.5: <p> <i>
* Convert growable (therefore mutable) bag of attribute values to immutable ones. Indeed, we must guarantee that attribute values remain constant during the evaluation of the request, as
* mandated by the XACML spec, section 7.3.5: <p> <i>
* "Regardless of any dynamic modifications of the request context during policy evaluation, the PDP SHALL behave as if each bag of attribute values is fully populated in the context before it is first tested, and is thereafter immutable during evaluation. (That is, every subsequent test of that attribute shall use the same bag of values that was initially tested.)"
* </i></p>
*/
......@@ -167,15 +156,13 @@ public final class DefaultRequestFilter extends BaseRequestFilter
namedAttributes.put(attrEntry.getKey(), attrEntry.getValue());
}
final Attributes catSpecificAttrsToIncludeInResult = categorySpecificAttributes
.getAttributesToIncludeInResult();
final Attributes catSpecificAttrsToIncludeInResult = categorySpecificAttributes.getAttributesToIncludeInResult();
if (catSpecificAttrsToIncludeInResult != null)
{
attributesToIncludeInResult.add(catSpecificAttrsToIncludeInResult);
}
}
return Collections.singletonList(new ImmutableIndividualDecisionRequest(namedAttributes,
extraContentsByCategory, attributesToIncludeInResult, isApplicablePolicyIdListReturned));
return Collections.singletonList(new ImmutableIndividualDecisionRequest(namedAttributes, extraContentsByCategory, attributesToIncludeInResult, isApplicablePolicyIdListReturned));
}
}
......@@ -24,11 +24,14 @@ import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.datatype.XMLGregorianCalendar;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.DecisionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Request;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Response;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Result;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.CloseablePDP;
import org.ow2.authzforce.core.pdp.api.DecisionCache;
......@@ -61,67 +64,56 @@ import org.slf4j.LoggerFactory;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.DecisionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Request;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Response;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Result;
/**
* This is the core XACML PDP engine implementation. To build an XACML policy
* engine, you start by instantiating this object directly or in a easier and
* preferred way, using {@link PdpConfigurationParser}.
* This is the core XACML PDP engine implementation. To build an XACML policy engine, you start by instantiating this object directly or in a easier and preferred way, using
* {@link PdpConfigurationParser}.
*
* @version $Id: $
*/
public final class PDPImpl implements CloseablePDP {
private static final IllegalArgumentException ILLEGAL_ARGUMENT_EXCEPTION = new IllegalArgumentException(
"No input Individual Decision Request");
public final class PDPImpl implements CloseablePDP
{
private static final IllegalArgumentException ILLEGAL_ARGUMENT_EXCEPTION = new IllegalArgumentException("No input Individual Decision Request");
// the logger we'll use for all messages
private static final Logger LOGGER = LoggerFactory.getLogger(PDPImpl.class);
/*
* The default behavior for getting the standard environment attributes
* (current date/time) is the one complying strictly with the XACML spec: if
* request does not have values for these attributes, the "context handler"
* (PDP in this case) must provide them. So we use PDP values if it does not
* override any existing value in the request.
* The default behavior for getting the standard environment attributes (current date/time) is the one complying strictly with the XACML spec: if request does not have values for these attributes,
* the "context handler" (PDP in this case) must provide them. So we use PDP values if it does not override any existing value in the request.
*/
private static final StandardEnvironmentAttributeSource DEFAULT_STD_ENV_ATTRIBUTE_SOURCE = StandardEnvironmentAttributeSource.REQUEST_ELSE_PDP;
/**
* Indeterminate response iff CombinedDecision element not supported because
* the request parser does not support any scheme from
* MultipleDecisionProfile section 2.
* Indeterminate response iff CombinedDecision element not supported because the request parser does not support any scheme from MultipleDecisionProfile section 2.
*/
private static final Response UNSUPPORTED_COMBINED_DECISION_RESPONSE = new Response(
Collections.<Result> singletonList(new Result(DecisionType.INDETERMINATE,
new StatusHelper(StatusHelper.STATUS_SYNTAX_ERROR, "Unsupported feature: CombinedDecision='true'"),
null, null, null, null)));
private static final Response UNSUPPORTED_COMBINED_DECISION_RESPONSE = new Response(Collections.<Result> singletonList(new Result(DecisionType.INDETERMINATE, new StatusHelper(
StatusHelper.STATUS_SYNTAX_ERROR, "Unsupported feature: CombinedDecision='true'"), null, null, null, null)));
private interface StandardEnvironmentAttributeIssuer {
private interface StandardEnvironmentAttributeIssuer
{
Map<AttributeGUID, Bag<?>> get();
}
private static final StandardEnvironmentAttributeIssuer NULL_STD_ENV_ATTRIBUTE_ISSUER = new StandardEnvironmentAttributeIssuer() {
private static final StandardEnvironmentAttributeIssuer NULL_STD_ENV_ATTRIBUTE_ISSUER = new StandardEnvironmentAttributeIssuer()
{
@Override
public Map<AttributeGUID, Bag<?>> get() {
public Map<AttributeGUID, Bag<?>> get()
{
return null;
}
};
private static final StandardEnvironmentAttributeIssuer DEFAULT_TZ_BASED_STD_ENV_ATTRIBUTE_ISSUER = new StandardEnvironmentAttributeIssuer() {
private static final StandardEnvironmentAttributeIssuer DEFAULT_TZ_BASED_STD_ENV_ATTRIBUTE_ISSUER = new StandardEnvironmentAttributeIssuer()
{
@Override
public Map<AttributeGUID, Bag<?>> get() {
public Map<AttributeGUID, Bag<?>> get()
{
/*
* Set the standard current date/time attribute according to XACML
* core spec:
* "This identifier indicates the current time at the context handler. In practice it is the time at which the request context was created."
* (§B.7). XACML standard (§10.2.5) says: "If values for these
* attributes are not present in the decision request, then their
* values MUST be supplied by the context handler".
* Set the standard current date/time attribute according to XACML core spec:
* "This identifier indicates the current time at the context handler. In practice it is the time at which the request context was created." (§B.7). XACML standard (§10.2.5) says: "If
* values for these attributes are not present in the decision request, then their values MUST be supplied by the context handler".
*/
// current datetime in default timezone
final DateTimeValue currentDateTimeValue = new DateTimeValue(new GregorianCalendar());
......@@ -131,51 +123,54 @@ public final class PDPImpl implements CloseablePDP {
Bags.singleton(StandardDatatypes.DATETIME_FACTORY.getDatatype(), currentDateTimeValue),
// current date
StandardEnvironmentAttribute.CURRENT_DATE.getGUID(),
Bags.singleton(StandardDatatypes.DATE_FACTORY.getDatatype(),
DateValue.getInstance(
(XMLGregorianCalendar) currentDateTimeValue.getUnderlyingValue().clone())),
Bags.singleton(StandardDatatypes.DATE_FACTORY.getDatatype(), DateValue.getInstance((XMLGregorianCalendar) currentDateTimeValue.getUnderlyingValue().clone())),
// current time
StandardEnvironmentAttribute.CURRENT_TIME.getGUID(),
Bags.singleton(StandardDatatypes.TIME_FACTORY.getDatatype(), TimeValue
.getInstance((XMLGregorianCalendar) currentDateTimeValue.getUnderlyingValue().clone())));
Bags.singleton(StandardDatatypes.TIME_FACTORY.getDatatype(), TimeValue.getInstance((XMLGregorianCalendar) currentDateTimeValue.getUnderlyingValue().clone())));
}
};
private static final DecisionResultFilter DEFAULT_RESULT_FILTER = new DecisionResultFilter() {
private static final DecisionResultFilter DEFAULT_RESULT_FILTER = new DecisionResultFilter()
{
private static final String ID = "urn:ow2:authzforce:feature:pdp:result-filter:default";
@Override
public String getId() {
public String getId()
{
return ID;
}
@Override
public List<Result> filter(final List<Result> results) {
public List<Result> filter(final List<Result> results)
{
return results;
}
@Override
public boolean supportsMultipleDecisionCombining() {
public boolean supportsMultipleDecisionCombining()
{
return false;
}
};
private static final class NonCachingIndividualDecisionRequestEvaluator extends IndividualDecisionRequestEvaluator {
private NonCachingIndividualDecisionRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator,
final StandardEnvironmentAttributeSource stdEnvAttributeSource) {
private static final class NonCachingIndividualDecisionRequestEvaluator extends IndividualDecisionRequestEvaluator
{
private NonCachingIndividualDecisionRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource)
{
super(rootPolicyEvaluator, stdEnvAttributeSource);
}
@Override
protected <INDIVIDUAL_DECISION_REQ_T extends IndividualDecisionRequest> List<Result> evaluate(
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests,
final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes) {
protected <INDIVIDUAL_DECISION_REQ_T extends IndividualDecisionRequest> List<Result> evaluate(final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests,
final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes)
{
final List<Result> results = new ArrayList<>(individualDecisionRequests.size());
for (final IndividualDecisionRequest individuaDecisionRequest : individualDecisionRequests) {
if (individuaDecisionRequest == null) {
throw new RuntimeException(
"One of the individual decision requests returned by the request filter is invalid (null).");
for (final IndividualDecisionRequest individuaDecisionRequest : individualDecisionRequests)
{
if (individuaDecisionRequest == null)
{
throw new RuntimeException("One of the individual decision requests returned by the request filter is invalid (null).");
}
final PdpDecisionResult decisionResult = evaluate(individuaDecisionRequest, pdpIssuedAttributes, false);
......@@ -187,75 +182,59 @@ public final class PDPImpl implements CloseablePDP {
}
private static final class CachingIndividualRequestEvaluator extends IndividualDecisionRequestEvaluator {
private static final class CachingIndividualRequestEvaluator extends IndividualDecisionRequestEvaluator
{
// the logger we'll use for all messages
private static final Logger _LOGGER = LoggerFactory.getLogger(CachingIndividualRequestEvaluator.class);
private static final Result INVALID_DECISION_CACHE_RESULT = new Result(DecisionType.INDETERMINATE,
new StatusHelper(StatusHelper.STATUS_PROCESSING_ERROR, "Internal error"), null, null, null, null);
private static final Result INVALID_DECISION_CACHE_RESULT = new Result(DecisionType.INDETERMINATE, new StatusHelper(StatusHelper.STATUS_PROCESSING_ERROR, "Internal error"), null, null, null,
null);
private final DecisionCache decisionCache;
private CachingIndividualRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator,
final StandardEnvironmentAttributeSource stdEnvAttributeSource, final DecisionCache decisionCache) {
private CachingIndividualRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource, final DecisionCache decisionCache)
{
super(rootPolicyEvaluator, stdEnvAttributeSource);
assert decisionCache != null;
this.decisionCache = decisionCache;
}
@Override
public <INDIVIDUAL_DECISION_REQ_T extends IndividualDecisionRequest> List<Result> evaluate(
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests,
final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes) {
final Map<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult> cachedResultsByRequest = decisionCache
.getAll(individualDecisionRequests);
if (cachedResultsByRequest == null) {
public <INDIVIDUAL_DECISION_REQ_T extends IndividualDecisionRequest> List<Result> evaluate(final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests,
final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes)
{
final Map<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult> cachedResultsByRequest = decisionCache.getAll(individualDecisionRequests);
if (cachedResultsByRequest == null)
{
// error, return indeterminate result as only result
_LOGGER.error("Invalid decision cache result: null");
return Collections.singletonList(INVALID_DECISION_CACHE_RESULT);
}
final List<Result> results = new ArrayList<>(individualDecisionRequests.size());
/*
* At least check that we have as many results from cache as input
* requests (For each request with no result in cache, there must
* still be an entry with value null.)
* There will be at most as many new results (not in cache) as there are individual decision requests
*/
if (cachedResultsByRequest.size() != individualDecisionRequests.size()) {
// error, return indeterminate result as only result
if (LOGGER.isErrorEnabled()) {
// Beware of autoboxing which causes call to
// Integer.valueOf(...)
_LOGGER.error(
"Invalid decision cache result: number of returned decision results ({}) != number of input (individual) decision requests ({})",
cachedResultsByRequest.size(), individualDecisionRequests.size());
}
return Collections.singletonList(INVALID_DECISION_CACHE_RESULT);
}
final Set<Entry<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult>> cachedRequestResultEntries = cachedResultsByRequest
.entrySet();
final List<Result> results = new ArrayList<>(cachedRequestResultEntries.size());
final Map<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult> newResultsByRequest = HashObjObjMaps
.newUpdatableMap();
for (final Entry<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult> cachedRequestResultPair : cachedRequestResultEntries) {
final Map<INDIVIDUAL_DECISION_REQ_T, PdpDecisionResult> newResultsByRequest = HashObjObjMaps.newUpdatableMap(individualDecisionRequests.size());
for (final INDIVIDUAL_DECISION_REQ_T individualDecisionRequest : individualDecisionRequests)
{
final PdpDecisionResult finalResult;
final INDIVIDUAL_DECISION_REQ_T individuaDecisionRequest = cachedRequestResultPair.getKey();
final PdpDecisionResult cachedResult = cachedRequestResultPair.getValue();
if (cachedResult == null) {
/*
* Check whether there is any decision result in cache for this request
*/
final PdpDecisionResult cachedResult = cachedResultsByRequest.get(individualDecisionRequest);
if (cachedResult == null)
{
// result not in cache -> evaluate request
if (individuaDecisionRequest == null) {
throw new RuntimeException(
"One of the entry keys (individual decision request) returned by the decision cache implementation '"
+ decisionCache + "' is invalid (null).");
}
finalResult = evaluate(individuaDecisionRequest, pdpIssuedAttributes, true);
newResultsByRequest.put(individuaDecisionRequest, finalResult);
} else {
finalResult = evaluate(individualDecisionRequest, pdpIssuedAttributes, true);
newResultsByRequest.put(individualDecisionRequest, finalResult);
}
else
{
finalResult = cachedResult;
}
results.add(finalResult.toXACMLResult(individuaDecisionRequest.getReturnedAttributes()));
results.add(finalResult.toXACMLResult(individualDecisionRequest.getReturnedAttributes()));
}
decisionCache.putAll(newResultsByRequest);
......@@ -272,33 +251,24 @@ public final class PDPImpl implements CloseablePDP {
private final int badRequestStatusDetailLevel;
/**
* Constructs a new <code>PDP</code> object with the given configuration
* information.
* Constructs a new <code>PDP</code> object with the given configuration information.
*
* @param attributeFactory
* attribute value factory - mandatory
* @param functionRegistry
* function registry - mandatory
* @param jaxbAttributeProviderConfs
* XML/JAXB configurations of Attribute Providers for
* AttributeDesignator/AttributeSelector evaluation; may be null
* for static expression evaluation (out of context), in which
* case AttributeSelectors/AttributeDesignators are not supported
* XML/JAXB configurations of Attribute Providers for AttributeDesignator/AttributeSelector evaluation; may be null for static expression evaluation (out of context), in which case
* AttributeSelectors/AttributeDesignators are not supported
* @param maxVariableReferenceDepth
* max depth of VariableReference chaining: VariableDefinition ->
* VariableDefinition ->... ('->' represents a
* VariableReference); strictly negative value means no limit
* max depth of VariableReference chaining: VariableDefinition -> VariableDefinition ->... ('->' represents a VariableReference); strictly negative value means no limit
*
* @param enableXPath
* allow XPath evaluation, i.e. AttributeSelectors and
* xpathExpressions (experimental, not for production, use with
* caution)
* allow XPath evaluation, i.e. AttributeSelectors and xpathExpressions (experimental, not for production, use with caution)
* @param requestFilterId
* ID of request filter (XACML Request processing prior to policy
* evaluation) - mandatory
* ID of request filter (XACML Request processing prior to policy evaluation) - mandatory
* @param decisionResultFilter
* decision result filter (XACML Result processing after policy
* evaluation, before creating/returning final XACML Response)
* decision result filter (XACML Result processing after policy evaluation, before creating/returning final XACML Response)
* @param jaxbDecisionCacheConf
* decision response cache XML/JAXB configuration
* @param jaxbRootPolicyProviderConf
......@@ -306,99 +276,70 @@ public final class PDPImpl implements CloseablePDP {
* @param combiningAlgRegistry
* XACML policy/rule combining algorithm registry - mandatory
* @param jaxbRefPolicyProviderConf
* policy-by-reference Provider's XML/JAXB configuration, for
* resolving policies referred to by Policy(Set)IdReference in
* policies found by root policy Provider
* policy-by-reference Provider's XML/JAXB configuration, for resolving policies referred to by Policy(Set)IdReference in policies found by root policy Provider
* @param maxPolicySetRefDepth
* max allowed PolicySetIdReference chain: PolicySet1
* (PolicySetIdRef1) -> PolicySet2 (PolicySetIdRef2) -> ...; a
* strictly negative value means no limit
* max allowed PolicySetIdReference chain: PolicySet1 (PolicySetIdRef1) -> PolicySet2 (PolicySetIdRef2) -> ...; a strictly negative value means no limit
* @param strictAttributeIssuerMatch
* true iff strict Attribute Issuer matching is enabled, i.e.
* AttributeDesignators without Issuer only match request
* Attributes without Issuer (and same AttributeId, Category...).
* This mode is not fully compliant with XACML 3.0, §5.29, in the
* case that the Issuer is indeed not present on a
* AttributeDesignator; but it performs better and is recommended
* when all AttributeDesignators have an Issuer (best practice).
* Reminder: the XACML 3.0 specification for AttributeDesignator
* evaluation (5.29) says: "If the Issuer is not present in the
* attribute designator, then the matching of the attribute to
* the named attribute SHALL be governed by AttributeId and
* DataType attributes alone." if one of the mandatory arguments
* is null
* true iff strict Attribute Issuer matching is enabled, i.e. AttributeDesignators without Issuer only match request Attributes without Issuer (and same AttributeId, Category...). This
* mode is not fully compliant with XACML 3.0, §5.29, in the case that the Issuer is indeed not present on a AttributeDesignator; but it performs better and is recommended when all
* AttributeDesignators have an Issuer (best practice). Reminder: the XACML 3.0 specification for AttributeDesignator evaluation (5.29) says: "If the Issuer is not present in the
* attribute designator, then the matching of the attribute to the named attribute SHALL be governed by AttributeId and DataType attributes alone." if one of the mandatory arguments is
* null
* @param stdEnvAttributeSource
* source for standard environment
* current-time/current-date/current-dateTime attribute values
* (request or PDP, etc.)
* source for standard environment current-time/current-date/current-dateTime attribute values (request or PDP, etc.)
* @param badRequestStatusDetailLevel
* level of detail in the StatusDetail returned in the
* Indeterminate Result when the Request format/syntax is invalid
* level of detail in the StatusDetail returned in the Indeterminate Result when the Request format/syntax is invalid
* @param environmentProperties
* PDP configuration environment properties
* @throws java.lang.IllegalArgumentException
* if there is not any extension found for type
* {@link org.ow2.authzforce.core.pdp.api.RequestFilter.Factory}
* with ID {@code requestFilterId}; or if one of the mandatory
* arguments is null; or if any Attribute Provider module
* created from {@code jaxbAttributeProviderConfs} does not
* provide any attribute; or it is in conflict with another one
* already registered to provide the same or part of the same
* attributes; of if there is no extension supporting
* {@code jaxbDecisionCacheConf}
* if there is not any extension found for type {@link org.ow2.authzforce.core.pdp.api.RequestFilter.Factory} with ID {@code requestFilterId}; or if one of the mandatory arguments is
* null; or if any Attribute Provider module created from {@code jaxbAttributeProviderConfs} does not provide any attribute; or it is in conflict with another one already registered to
* provide the same or part of the same attributes; of if there is no extension supporting {@code jaxbDecisionCacheConf}
* @throws java.io.IOException
* error closing the root policy Provider when static resolution
* is to be used; or error closing the attribute Provider
* modules created from {@code jaxbAttributeProviderConfs}, when
* error closing the root policy Provider when static resolution is to be used; or error closing the attribute Provider modules created from {@code jaxbAttributeProviderConfs}, when
* and before an {@link IllegalArgumentException} is raised
*/
public PDPImpl(final DatatypeFactoryRegistry attributeFactory, final FunctionRegistry functionRegistry,
final List<AbstractAttributeProvider> jaxbAttributeProviderConfs, final int maxVariableReferenceDepth,
final boolean enableXPath, final CombiningAlgRegistry combiningAlgRegistry,
final AbstractPolicyProvider jaxbRootPolicyProviderConf,
final AbstractPolicyProvider jaxbRefPolicyProviderConf, final int maxPolicySetRefDepth,
final String requestFilterId, final boolean strictAttributeIssuerMatch,
final StandardEnvironmentAttributeSource stdEnvAttributeSource,
final DecisionResultFilter decisionResultFilter, final AbstractDecisionCache jaxbDecisionCacheConf,
final int badRequestStatusDetailLevel, final EnvironmentProperties environmentProperties)
throws IllegalArgumentException, IOException {
final RequestFilter.Factory requestFilterFactory = requestFilterId == null
? DefaultRequestFilter.LaxFilterFactory.INSTANCE
: PdpExtensionLoader.getExtension(RequestFilter.Factory.class, requestFilterId);
final RequestFilter requestFilter = requestFilterFactory.getInstance(attributeFactory,
strictAttributeIssuerMatch, enableXPath, XMLUtils.SAXON_PROCESSOR);
final RootPolicyEvaluators.Base candidateRootPolicyEvaluator = new RootPolicyEvaluators.Base(attributeFactory,
functionRegistry, jaxbAttributeProviderConfs, maxVariableReferenceDepth, enableXPath,
combiningAlgRegistry, jaxbRootPolicyProviderConf, jaxbRefPolicyProviderConf, maxPolicySetRefDepth,
strictAttributeIssuerMatch, environmentProperties);
public PDPImpl(final DatatypeFactoryRegistry attributeFactory, final FunctionRegistry functionRegistry, final List<AbstractAttributeProvider> jaxbAttributeProviderConfs,
final int maxVariableReferenceDepth, final boolean enableXPath, final CombiningAlgRegistry combiningAlgRegistry, final AbstractPolicyProvider jaxbRootPolicyProviderConf,
final AbstractPolicyProvider jaxbRefPolicyProviderConf, final int maxPolicySetRefDepth, final String requestFilterId, final boolean strictAttributeIssuerMatch,
final StandardEnvironmentAttributeSource stdEnvAttributeSource, final DecisionResultFilter decisionResultFilter, final AbstractDecisionCache jaxbDecisionCacheConf,
final int badRequestStatusDetailLevel, final EnvironmentProperties environmentProperties) throws IllegalArgumentException, IOException
{
final RequestFilter.Factory requestFilterFactory = requestFilterId == null ? DefaultRequestFilter.LaxFilterFactory.INSTANCE : PdpExtensionLoader.getExtension(RequestFilter.Factory.class,
requestFilterId);
final RequestFilter requestFilter = requestFilterFactory.getInstance(attributeFactory, strictAttributeIssuerMatch, enableXPath, XMLUtils.SAXON_PROCESSOR);
final RootPolicyEvaluators.Base candidateRootPolicyEvaluator = new RootPolicyEvaluators.Base(attributeFactory, functionRegistry, jaxbAttributeProviderConfs, maxVariableReferenceDepth,
enableXPath, combiningAlgRegistry, jaxbRootPolicyProviderConf, jaxbRefPolicyProviderConf, maxPolicySetRefDepth, strictAttributeIssuerMatch, environmentProperties);
// Use static resolution if possible
final RootPolicyEvaluator staticRootPolicyEvaluator = candidateRootPolicyEvaluator.toStatic();
if (staticRootPolicyEvaluator == null) {
if (staticRootPolicyEvaluator == null)
{
this.rootPolicyEvaluator = candidateRootPolicyEvaluator;
} else {
}
else
{
this.rootPolicyEvaluator = staticRootPolicyEvaluator;
}
this.reqFilter = requestFilter;
// decision cache
if (jaxbDecisionCacheConf == null) {
if (jaxbDecisionCacheConf == null)
{
this.decisionCache = null;
} else {
final DecisionCache.Factory<AbstractDecisionCache> responseCacheStoreFactory = PdpExtensionLoader
.getJaxbBoundExtension(DecisionCache.Factory.class, jaxbDecisionCacheConf.getClass());
}
else
{
final DecisionCache.Factory<AbstractDecisionCache> responseCacheStoreFactory = PdpExtensionLoader.getJaxbBoundExtension(DecisionCache.Factory.class, jaxbDecisionCacheConf.getClass());
this.decisionCache = responseCacheStoreFactory.getInstance(jaxbDecisionCacheConf);
}
final StandardEnvironmentAttributeSource validStdEnvAttrSrc = stdEnvAttributeSource == null
? DEFAULT_STD_ENV_ATTRIBUTE_SOURCE : stdEnvAttributeSource;
this.pdpStdEnvAttributeIssuer = validStdEnvAttrSrc == StandardEnvironmentAttributeSource.REQUEST_ONLY
? NULL_STD_ENV_ATTRIBUTE_ISSUER : DEFAULT_TZ_BASED_STD_ENV_ATTRIBUTE_ISSUER;
this.individualReqEvaluator = this.decisionCache == null
? new NonCachingIndividualDecisionRequestEvaluator(rootPolicyEvaluator, validStdEnvAttrSrc)
: new CachingIndividualRequestEvaluator(rootPolicyEvaluator, validStdEnvAttrSrc, this.decisionCache);
final StandardEnvironmentAttributeSource validStdEnvAttrSrc = stdEnvAttributeSource == null ? DEFAULT_STD_ENV_ATTRIBUTE_SOURCE : stdEnvAttributeSource;
this.pdpStdEnvAttributeIssuer = validStdEnvAttrSrc == StandardEnvironmentAttributeSource.REQUEST_ONLY ? NULL_STD_ENV_ATTRIBUTE_ISSUER : DEFAULT_TZ_BASED_STD_ENV_ATTRIBUTE_ISSUER;
this.individualReqEvaluator = this.decisionCache == null ? new NonCachingIndividualDecisionRequestEvaluator(rootPolicyEvaluator, validStdEnvAttrSrc) : new CachingIndividualRequestEvaluator(
rootPolicyEvaluator, validStdEnvAttrSrc, this.decisionCache);
this.resultFilter = decisionResultFilter == null ? DEFAULT_RESULT_FILTER : decisionResultFilter;
this.badRequestStatusDetailLevel = badRequestStatusDetailLevel;
......@@ -406,61 +347,56 @@ public final class PDPImpl implements CloseablePDP {
/** {@inheritDoc} */
@Override
public <R extends IndividualDecisionRequest> List<Result> evaluate(final List<R> individualDecisionRequests) {
if (individualDecisionRequests == null) {
public <R extends IndividualDecisionRequest> List<Result> evaluate(final List<R> individualDecisionRequests)
{
if (individualDecisionRequests == null)
{
throw ILLEGAL_ARGUMENT_EXCEPTION;
}
/*
* Evaluate the individual decision requests with extra common
* attributes set by the PDP once for all: standard environment
* attributes, i.e. current-time, etc. XACML standard (§10.2.5) says:
* "If values for these attributes are not present in the decision request, then their values MUST be supplied by the context handler"
* . These current date/time values must be set here once before every
* individual request is evaluated to make sure they all use the same
* value for current-time/current-date/current-dateTime, if they use the
* one from PDP.
* Evaluate the individual decision requests with extra common attributes set by the PDP once for all: standard environment attributes, i.e. current-time, etc. XACML standard (§10.2.5) says:
* "If values for these attributes are not present in the decision request, then their values MUST be supplied by the context handler" . These current date/time values must be set here once
* before every individual request is evaluated to make sure they all use the same value for current-time/current-date/current-dateTime, if they use the one from PDP.
*/
final List<Result> results = individualReqEvaluator.evaluate(individualDecisionRequests,
this.pdpStdEnvAttributeIssuer.get());
final List<Result> results = individualReqEvaluator.evaluate(individualDecisionRequests, this.pdpStdEnvAttributeIssuer.get());
return resultFilter.filter(results);
}
/** {@inheritDoc} */
@Override
public Response evaluate(final Request request, final Map<String, String> namespaceURIsByPrefix) {
if (request == null) {
public Response evaluate(final Request request, final Map<String, String> namespaceURIsByPrefix)
{
if (request == null)
{
throw ILLEGAL_ARGUMENT_EXCEPTION;
}
/*
* No support for CombinedDecision = true if no decisionCombiner
* defined. (The use of the CombinedDecision attribute is specified in
* Multiple Decision Profile.)
* No support for CombinedDecision = true if no decisionCombiner defined. (The use of the CombinedDecision attribute is specified in Multiple Decision Profile.)
*/
if (request.isCombinedDecision() && !resultFilter.supportsMultipleDecisionCombining()) {
if (request.isCombinedDecision() && !resultFilter.supportsMultipleDecisionCombining())
{
/*
* According to XACML core spec, 5.42, "If the PDP does not
* implement the relevant functionality in [Multiple Decision
* Profile], then the PDP must return an Indeterminate with a status
* code of urn:oasis:names:tc:xacml:1.0:status:processing-error if