Commit 1fac5614 authored by cdanger's avatar cdanger

Prepared changelog for next release

parent c3018d38
......@@ -2,6 +2,29 @@
All notable changes to this project are documented in this file following the [Keep a CHANGELOG](http://keepachangelog.com) conventions.
## Unreleased
### Fixed
- #22 (OW2): When handling the same XACML Request twice in the same JVM with the root PolicySet using deny-unless-permit algorithm over a Policy returning simple Deny (no status/obligation/advice) and a Policy returning Permit/Deny with obligations/advice, the obligation is duplicated in the final result at the second time this situation occurs.
- XACML StatusCode XML serialization/marshalling error when Missing Attribute info that is no valid anyURI is returned by PDP in a Indeterminate Result
- Memory management issue: native RootPolicyProvider modules keeping a reference to static refPolicyProvider, even after policies have been resolved statically at initialization time, preventing garbage collection and memory saving.
- Calls to Logger impacted negatively by autoboxing
### Removed
- 'functionSet' element no longer supported in PDP XML configuration schema
### Changed
- Parent project version: authzforce-ce-parent: 3.4.0
- Dependency version: authzforce-ce-core-pdp-api: ???: requires to pass new EnvironmentProperties parameter to AttributeProvider module factories for using global PDP environment properties (such as PDP configuration file's parent directory)
- Interpretation of XACML Request flag ReturnPolicyId=true, considering a policy "applicable" if and only if the decision is not NotApplicable and if it is not a root policy, the same goes for the enclosing policy. See also the discussion on the xacml-comment mailing list: https://lists.oasis-open.org/archives/xacml-comment/201605/msg00004.html
### Added
- New feature enabled by PDP configuration parameter: enum 'standardEnvAttributeSource' to set the source for the Standard Current Time Environment Attribute values (current-date, current-time, current-dateTime): PDP_ONLY, REQUEST_ELSE_PDP, REQUEST_ONLY
- enum StandardFunction that enumerates all standard XACML function IDs
- enum StandardEnvironmentAttribute that enumerates all XACML standard environment attribute identifiers
- enum StandardCombiningAlgoritm that enumerates all standard XACML combining algorithms
### Deprecated
- Ability to marshall internal classes derived from XACML/JAXB Expressions back to the original JAXB Expression: it may consume a significant amount of extra memory, esp. when a nested PolicySet has deep nested Policy(Set)s, and it forces our internal evaluation classes to duplicate information and override many methods. Also it ties the internal model to the JAXB model which is far from optimal for evaluation purposes. Now we consider no longer the responsibility of the PDP to be able to marshall such XACML instances, but the caller's; in particular the classes ApplyExpression, AttributeDesignatorExpression, AttributeSelectorExpression, AttributeAssigmnentExpressionEvaluator no longer extend JAXB classes.
## 4.0.2
### Fixed
......
......@@ -42,24 +42,29 @@ public final class AllOfEvaluator
private static final IllegalArgumentException NO_MATCH_EXCEPTION = new IllegalArgumentException(
"<AllOf> empty. Must contain at least one <Match>");
// Store the list of Matches as evaluatable Match types to avoid casting from JAXB MatchType
// Store the list of Matches as evaluatable Match types to avoid casting
// from JAXB MatchType
// during evaluation
private final transient List<MatchEvaluator> evaluatableMatchList;
/**
* Instantiates AllOf (evaluator) from XACML-Schema-derived <code>AllOf</code>.
* Instantiates AllOf (evaluator) from XACML-Schema-derived
* <code>AllOf</code>.
*
* @param jaxbMatches
* XACML-schema-derived JAXB Match elements
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default XPath version
* XPath compiler corresponding to enclosing policy(set) default
* XPath version
* @param expFactory
* Expression factory
* @throws java.lang.IllegalArgumentException
* one of the child Match elements is invalid
* null {@code expFactory} or null/empty {@code jaxbMatches} or
* one of the child Match elements in {@code jaxbMatches} is
* invalid
*/
public AllOfEvaluator(List<Match> jaxbMatches, XPathCompiler xPathCompiler, ExpressionFactory expFactory)
throws IllegalArgumentException
public AllOfEvaluator(final List<Match> jaxbMatches, final XPathCompiler xPathCompiler,
final ExpressionFactory expFactory) throws IllegalArgumentException
{
if (jaxbMatches == null || jaxbMatches.isEmpty())
{
......@@ -75,7 +80,7 @@ public final class AllOfEvaluator
{
matchEvaluator = new MatchEvaluator(jaxbMatch, xPathCompiler, expFactory);
}
catch (IllegalArgumentException e)
catch (final IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <AllOf>'s <Match>#" + matchIndex, e);
}
......@@ -86,8 +91,9 @@ public final class AllOfEvaluator
}
/**
* Determines whether this <code>AllOf</code> matches the input request (whether it is applicable).Here is the table
* shown in the specification: <code>
* Determines whether this <code>AllOf</code> matches the input request
* (whether it is applicable).Here is the table shown in the specification:
* <code>
* <Match> values <AllOf> value
* All True “Match�?
* No False and at least
......@@ -101,7 +107,7 @@ public final class AllOfEvaluator
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* Indeterminate
*/
public boolean match(EvaluationContext context) throws IndeterminateEvaluationException
public boolean match(final EvaluationContext context) throws IndeterminateEvaluationException
{
// atLeastOneIndeterminate = true iff lastIndeterminate != null
IndeterminateEvaluationException lastIndeterminate = null;
......@@ -123,15 +129,17 @@ public final class AllOfEvaluator
isMatched = matchEvaluator.match(context);
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Boolean.valueOf(...), Integer.valueOf(...)
// Beware of autoboxing which causes call to
// Boolean.valueOf(...), Integer.valueOf(...)
LOGGER.debug("AllOf/Match#{} -> {}", childIndex, isMatched);
}
}
catch (IndeterminateEvaluationException e)
catch (final IndeterminateEvaluationException e)
{
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Integer.valueOf(...)
// Beware of autoboxing which causes call to
// Integer.valueOf(...)
LOGGER.debug("AllOf/Match#{} -> Indeterminate", childIndex, e);
}
lastIndeterminate = e;
......
......@@ -45,24 +45,29 @@ public final class AnyOfEvaluator
private static final IllegalArgumentException NO_ALL_OF_EXCEPTION = new IllegalArgumentException(
"<AnyOf> empty. Must contain at least one <AllOf>");
// Store the list of AllOf as evaluatable AllOf types to avoid casting from JAXB AllOfType
// Store the list of AllOf as evaluatable AllOf types to avoid casting from
// JAXB AllOfType
// during evaluation
private final transient List<AllOfEvaluator> evaluatableAllOfList;
/**
* Constructor that creates a new <code>AnyOf</code> evaluator based on the given XACML-schema-derived JAXB AnyOf.
* Constructor that creates a new <code>AnyOf</code> evaluator based on the
* given XACML-schema-derived JAXB AnyOf.
*
* @param jaxbAllOfList
* JAXB AllOf elements
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default XPath version
* XPath compiler corresponding to enclosing policy(set) default
* XPath version
* @param expFactory
* Expression factory
* @throws java.lang.IllegalArgumentException
* if one of the child AllOf elements is invalid
* null {@code expFactory} or null/empty {@code jaxbAllOfList}
* or one of the child Match elements in one of the AllOf
* elements of {@code jaxbAllOfList} is invalid
*/
public AnyOfEvaluator(List<AllOf> jaxbAllOfList, XPathCompiler xPathCompiler, ExpressionFactory expFactory)
throws IllegalArgumentException
public AnyOfEvaluator(final List<AllOf> jaxbAllOfList, final XPathCompiler xPathCompiler,
final ExpressionFactory expFactory) throws IllegalArgumentException
{
if (jaxbAllOfList == null || jaxbAllOfList.isEmpty())
{
......@@ -78,7 +83,7 @@ public final class AnyOfEvaluator
{
allOfEvaluator = new AllOfEvaluator(jaxbAllOf.getMatches(), xPathCompiler, expFactory);
}
catch (IllegalArgumentException e)
catch (final IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <AnyOf>'s <AllOf>#" + matchIndex, e);
}
......@@ -89,8 +94,9 @@ public final class AnyOfEvaluator
}
/**
* Determines whether this <code>AnyOf</code> matches the input request (whether it is applicable). If all the AllOf
* values is No_Match so it's a No_Match. If all matches it's a Match. If None matches and at least one
* Determines whether this <code>AnyOf</code> matches the input request
* (whether it is applicable). If all the AllOf values is No_Match so it's a
* No_Match. If all matches it's a Match. If None matches and at least one
* “Indeterminate�? it's Indeterminate
*
* <pre>
......@@ -107,7 +113,7 @@ public final class AnyOfEvaluator
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* if Indeterminate
*/
public boolean match(EvaluationContext context) throws IndeterminateEvaluationException
public boolean match(final EvaluationContext context) throws IndeterminateEvaluationException
{
// atLeastOneIndeterminate = true iff lastIndeterminate != null
IndeterminateEvaluationException lastIndeterminate = null;
......@@ -129,15 +135,17 @@ public final class AnyOfEvaluator
isMatched = allOfEvaluator.match(context);
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Boolean.valueOf(...), Integer.valueOf(...)
// Beware of autoboxing which causes call to
// Boolean.valueOf(...), Integer.valueOf(...)
LOGGER.debug("AnyOf/AllOf#{} -> {}", childIndex, isMatched);
}
}
catch (IndeterminateEvaluationException e)
catch (final IndeterminateEvaluationException e)
{
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Integer.valueOf(...)
// Beware of autoboxing which causes call to
// Integer.valueOf(...)
LOGGER.debug("AnyOf/AllOf#{} -> Indeterminate", childIndex, e);
}
lastIndeterminate = e;
......@@ -165,7 +173,8 @@ public final class AnyOfEvaluator
return false;
}
// No Match and at least one Indeterminate (lastIndeterminate != null) -> Indeterminate
// No Match and at least one Indeterminate (lastIndeterminate != null)
// -> Indeterminate
throw new IndeterminateEvaluationException("Error evaluating <AnyOf>'s <AllOf>#" + lastIndeterminateChildIndex,
lastIndeterminate.getStatusCode(), lastIndeterminate);
}
......
......@@ -44,7 +44,8 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.Match;
*
* @version $Id: $
*/
public final class MatchEvaluator {
public final class MatchEvaluator
{
private static final IllegalArgumentException NULL_XACML_MATCH_ARGUMENT_EXCEPTION = new IllegalArgumentException(
"Undefined input XACML Match element");
......@@ -70,15 +71,18 @@ public final class MatchEvaluator {
* XPath compiler corresponding to enclosing policy(set) default
* XPath version
* @throws java.lang.IllegalArgumentException
* invalid <code>jaxbMatch</code>
* null {@code expFactory} or null/empty {@code jaxbMatch}
*/
public MatchEvaluator(final Match jaxbMatch, final XPathCompiler xPathCompiler, final ExpressionFactory expFactory)
throws IllegalArgumentException {
if (jaxbMatch == null) {
throws IllegalArgumentException
{
if (jaxbMatch == null)
{
throw NULL_XACML_MATCH_ARGUMENT_EXCEPTION;
}
if (expFactory == null) {
if (expFactory == null)
{
throw NULL_XACML_EXPRESSION_FACTORY_ARGUMENT_EXCEPTION;
}
......@@ -86,7 +90,8 @@ public final class MatchEvaluator {
// Target matchFunction
final String matchId = jaxbMatch.getMatchId();
final Function<?> matchFunction = expFactory.getFunction(matchId);
if (matchFunction == null) {
if (matchFunction == null)
{
throw new IllegalArgumentException("Unsupported function for MatchId: " + matchId);
}
......@@ -99,9 +104,12 @@ public final class MatchEvaluator {
final AttributeValueType attributeValue = jaxbMatch.getAttributeValue();
final Expression<? extends AttributeValue> attrValueExpr;
try {
try
{
attrValueExpr = expFactory.getInstance(attributeValue, xPathCompiler);
} catch (final IllegalArgumentException e) {
}
catch (final IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <Match>'s <AttributeValue>", e);
}
......@@ -110,16 +118,20 @@ public final class MatchEvaluator {
// attributeValue, bagExpression)
final Function<BooleanValue> anyOfFunc = (Function<BooleanValue>) expFactory
.getFunction(StandardFunction.ANY_OF.getId());
if (anyOfFunc == null) {
if (anyOfFunc == null)
{
throw new IllegalArgumentException(
"Unsupported function '" + StandardFunction.ANY_OF.getId() + "' required for Match evaluation");
}
final List<Expression<?>> anyOfFuncInputs = Arrays.<Expression<?>> asList(matchFunction, attrValueExpr,
bagExpression);
try {
try
{
this.anyOfFuncCall = anyOfFunc.newCall(anyOfFuncInputs);
} catch (final IllegalArgumentException e) {
}
catch (final IllegalArgumentException e)
{
throw new IllegalArgumentException(
"Invalid inputs (Expressions) to the Match (validated using the equivalent standard 'any-of' function definition): "
+ anyOfFuncInputs,
......@@ -138,11 +150,15 @@ public final class MatchEvaluator {
* error occurred evaluating the Match element in this
* evaluation {@code context}
*/
public boolean match(final EvaluationContext context) throws IndeterminateEvaluationException {
public boolean match(final EvaluationContext context) throws IndeterminateEvaluationException
{
final BooleanValue anyOfFuncCallResult;
try {
try
{
anyOfFuncCallResult = anyOfFuncCall.evaluate(context);
} catch (final IndeterminateEvaluationException e) {
}
catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException("Error evaluating Match (with equivalent 'any-of' function)",
e.getStatusCode(), e);
}
......
/**
* Copyright (C) 2012-2016 Thales Services SAS.
*
* This file is part of AuthZForce CE.
*
* AuthZForce CE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AuthZForce CE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AuthZForce CE. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.List;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOf;
/**
* Represents the TargetType XML type in XACML.
*
* @version $Id: $
*/
public final class TargetEvaluator implements BooleanEvaluator
{
private static final IllegalArgumentException NULL_OR_EMPTY_XACML_ANYOF_LIST_ARGUMENT_EXCEPTION = new IllegalArgumentException(
"Cannot create Target evaluator: no input XACML/JAXB AnyOf element");
/**
* Logger used for all classes
*/
private static final Logger LOGGER = LoggerFactory.getLogger(TargetEvaluator.class);
// Have a copy of AnyOf evaluators to avoid cast from JAXB AnyOf in super JAXB type
// non-null
private final List<AnyOfEvaluator> anyOfEvaluatorList;
/**
* Instantiates Target (evaluator) from XACML-Schema-derived <code>Target</code>.
*
* @param jaxbAnyOfList
* XACML-schema-derived JAXB AnyOf elements
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default XPath version
* @param expFactory
* Expression factory
* @throws java.lang.IllegalArgumentException
* if one of the child AnyOf elements is invalid
*/
public TargetEvaluator(List<AnyOf> jaxbAnyOfList, XPathCompiler xPathCompiler, ExpressionFactory expFactory)
throws IllegalArgumentException
{
if (jaxbAnyOfList == null || jaxbAnyOfList.isEmpty())
{
throw NULL_OR_EMPTY_XACML_ANYOF_LIST_ARGUMENT_EXCEPTION;
}
anyOfEvaluatorList = new ArrayList<>(jaxbAnyOfList.size());
int childIndex = 0;
for (final AnyOf jaxbAnyOf : jaxbAnyOfList)
{
final AnyOfEvaluator anyOfEvaluator;
try
{
anyOfEvaluator = new AnyOfEvaluator(jaxbAnyOf.getAllOves(), xPathCompiler, expFactory);
}
catch (IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <Target>'s <AnyOf>#" + childIndex, e);
}
anyOfEvaluatorList.add(anyOfEvaluator);
childIndex++;
}
}
/**
* Determines whether this <code>Target</code> matches the input request (whether it is applicable). If any of the
* AnyOf doesn't match the request context so it's a NO_MATCH result. Here is the table shown in the specification:
* <code>
* <AnyOf> values <Target> value
* All Match? Match?
* At Least one "No Match" No Match?
* Otherwise Indeterminate?
* </code> Also if Target empty (no AnyOf), return "Match"
*
* @param context
* the representation of the request
* @return true if and only if Match (else No-match)
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* if Indeterminate (error evaluating target)
*/
@Override
public boolean evaluate(EvaluationContext context) throws IndeterminateEvaluationException
{
// logic is quite similar to AllOf evaluation
// at the end, lastIndeterminate == null iff no Indeterminate occurred
IndeterminateEvaluationException lastIndeterminate = null;
// index of the current AnyOf in this Target
int childIndex = 0;
// index of last Indeterminate for enhanced error message
int lastIndeterminateChildIndex = -1;
/*
* By construction, there must be at least one Match
*/
for (final AnyOfEvaluator anyOfEvaluator : anyOfEvaluatorList)
{
final boolean isMatched;
try
{
isMatched = anyOfEvaluator.match(context);
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Boolean.valueOf(...), Integer.valueOf(...)
LOGGER.debug("Target/AnyOf#{} -> {}", childIndex, isMatched);
}
}
catch (IndeterminateEvaluationException e)
{
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Integer.valueOf(...)
LOGGER.debug("Target/AnyOf#{} -> Indeterminate", childIndex, e);
}
lastIndeterminate = e;
lastIndeterminateChildIndex = childIndex;
continue;
}
/*
* At least one False ("No match") -> No match
*/
if (!isMatched)
{
return false;
}
// True (Match) -> continue, all must be true to match
childIndex += 1;
}
// No False (=NO_MATCH) occurred
// lastIndeterminate == null iff no Indeterminate occurred
if (lastIndeterminate == null)
{
// No False/Indeterminate, i.e. all True -> Match
return true;
}
// No False but at least one Indeterminate (lastIndeterminate != null)
throw new IndeterminateEvaluationException("Error evaluating <Target>/<AnyOf>#" + lastIndeterminateChildIndex,
lastIndeterminate.getStatusCode(), lastIndeterminate);
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -125,7 +125,7 @@
'com.example.FooFunction' -
on the classpath implementing
interface
'com.sun.xacml.Function' with zero-arg constructor, such
'org.ow2.authzforce.core.pdp.api.func.Function' with zero-arg constructor, such
that this URI equals: new
com.example.FooFunction().getId().
</documentation>
......@@ -139,7 +139,7 @@
'com.example.FooCombiningAlg' - on the
classpath
implementing interface
'org.ow2.authzforce.core.pdp.api.CombiningAlg' with
'org.ow2.authzforce.core.pdp.api.combining.CombiningAlg' with
zero-arg
constructor,
such that this URI equals: new
......@@ -157,7 +157,7 @@
the
classpath
implementing interface
'org.ow2.authzforce.core.pdp.api.RefPolicyProviderModule.Factory&lt;CONF_T&gt;'
'org.ow2.authzforce.core.pdp.api.policy.RefPolicyProviderModule.Factory&lt;CONF_T&gt;'
with zero-arg constructor, where CONF_T is the JAXB type bound
to
this XML
......@@ -180,7 +180,7 @@
PDP
configuration file, so that Policy Provider
implementations can use
org.ow2.authzforce.pd.api.EnvironmentProperties#replacePlaceholders()
org.ow2.authzforce.pdp.api.EnvironmentProperties#replacePlaceholders()
to
replace ${PARENT_DIR} placeholder with this
value, and
......@@ -212,13 +212,13 @@
say
'com.example.FooRootPolicyProviderModuleFactory' - on the
classpath implementing interface
'org.ow2.authzforce.core.pdp.api.RootPolicyProviderModule.Factory&lt;CONF_T&gt;'
'org.ow2.authzforce.core.pdp.api.policy.RootPolicyProviderModule.Factory&lt;CONF_T&gt;'
with
zero-arg
constructor, where CONF_T is the JAXB type bound to
this XML element type.
This class may also implement
'org.ow2.authzforce.core.pdp.api.RefPolicyProviderModule.Factory&lt;CONF_T&gt;'
'org.ow2.authzforce.core.pdp.api.policy.RefPolicyProviderModule.Factory&lt;CONF_T&gt;'
to
be used
as
......@@ -236,7 +236,7 @@
PDP
configuration file, so that Policy Provider
implementations can use
org.ow2.authzforce.pd.api.EnvironmentProperties#replacePlaceholders()
org.ow2.authzforce.pdp.api.EnvironmentProperties#replacePlaceholders()
to
replace ${PARENT_DIR} placeholder with this
value, and
......@@ -345,7 +345,7 @@
it performs better and is recommended when all AttributeDesignators have an Issuer (best practice). Indeed, the XACML 3.0 Attribute Evaluation section
§5.29 says: "If the Issuer is not present in the AttributeDesignator, then the matching of the
attribute to the named attribute SHALL be governed by AttributeId and DataType attributes alone."
Therefore, if strictAttributeIssuerMatch is false, since policies may use AttributeDesignators without Issuer,
Therefore, if 'strictAttributeIssuerMatch' is false, since policies may use AttributeDesignators without Issuer,
if the requests are using matching Attributes but with none, one or more different Issuers, this PDP
engine has to gather all the values from all the attributes with matching Category/AttributeId but
with any Issuer or no Issuer. Therefore, in order to stay compliant with §5.29 and still enforce best
......@@ -401,8 +401,8 @@
Request. At
the end,
the results (one per Individual Decision
Request) may be combined by a DecisionCombiner specified by next
attribute 'decisionCombiner'.
Request) may be combined by a ResultFilter specified by next
attribute 'resultFilter'.
</p>
<p>There must be one and only one Java class - say
'com.example.FooRequestFilter' - on the classpath implementing
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment