Commit a0d846f5 authored by cdanger's avatar cdanger

Merge branch 'release/13.2.0'

parents 8878b003 983d5ecf
......@@ -6,6 +6,16 @@ All notable changes to this project are documented in this file following the [K
- Issues reported on [OW2's JIRA](https://jira.ow2.org/browse/AUTHZFORCE/) are referenced in the form of `[JIRA-N]`, where N is the issue number.
- Issues reported on [OW2's GitLab](https://gitlab.ow2.org/authzforce/core/issues) are referenced in the form of `[GL-N]`, where N is the issue number.
## 13.2.0
### Changed
- Maven dependency versions:
- `authzforce-ce-core-pdp-api`: 15.2.0 (change in `ExpressionFactory` interface: new method `getVariableExpression(variableId)`)
- Policy / `VariableDefinition` evaluation: a XACML Variable expressions is now evaluated and the Variable assigned in the EvaluationContext where the `VariableDefinition` is defined (as opposed to previous behavior which consisted in lazy evaluation, ie only when used in a corresponding `VariableReference`), making the Variable's value available not only to `VariableReference` but also PDP extensions such as Attribute Providers, even if no corresponding `VariableReference` occurs in the policy)
- `Time-in-range` function optimized (removed useless code)
- `GenericAttributeProviderBasedAttributeDesignatorExpression` class moved to dependency authzforce-ce-core-pdp-api
## 13.1.0
### Changed
- Maven parent project version: 7.3.0
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-cli</artifactId>
......@@ -30,12 +30,12 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-engine</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
</dependency>
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-io-xacml-json</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
......@@ -46,7 +46,7 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-testutils</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-engine</artifactId>
......
......@@ -32,6 +32,7 @@ import org.ow2.authzforce.core.pdp.api.expression.ConstantExpression;
import org.ow2.authzforce.core.pdp.api.expression.Expression;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
import org.ow2.authzforce.core.pdp.api.expression.FunctionExpression;
import org.ow2.authzforce.core.pdp.api.expression.GenericAttributeProviderBasedAttributeDesignatorExpression;
import org.ow2.authzforce.core.pdp.api.expression.VariableReference;
import org.ow2.authzforce.core.pdp.api.func.Function;
import org.ow2.authzforce.core.pdp.api.value.AttributeValue;
......@@ -171,6 +172,9 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
*
* Evaluates the referenced expression using the given context, and either returns an error or a resulting value. If this doesn't reference an evaluatable expression (eg, a single Function)
* then this will throw an exception.
* <p>
* The policy evaluator should call this when starting the evaluation of the policy where the VariableDefinition occurs, then cache the value in the evaluation context with
* {@link EvaluationContext#putVariableIfAbsent(String, Value)}.
*/
@Override
public V evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
......@@ -233,6 +237,9 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
*
* Evaluates the referenced expression using the given context, and either returns an error or a resulting value. If this doesn't reference an evaluatable expression (eg, a single Function)
* then this will throw an exception.
* <p>
* The policy evaluator should call this when starting the evaluation of the policy where the VariableDefinition occurs, then cache the value in the evaluation context with
* {@link EvaluationContext#putVariableIfAbsent(String, Value)}.
*/
@Override
public V evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
......@@ -414,6 +421,12 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
return idToVariableMap.putIfAbsent(varId, var);
}
@Override
public VariableReference<?> getVariableExpression(final String varId)
{
return idToVariableMap.get(varId);
}
/** {@inheritDoc} */
@Override
public VariableReference<?> removeVariable(final String varId)
......@@ -532,7 +545,8 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
if (expr instanceof ApplyType)
{
expression = ApplyExpressions.newInstance((ApplyType) expr, xPathCompiler, this, longestVarRefChain);
} else if (expr instanceof AttributeDesignatorType)
}
else if (expr instanceof AttributeDesignatorType)
{
if (this.attributeProvider == null)
{
......@@ -552,7 +566,8 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
}
expression = new GenericAttributeProviderBasedAttributeDesignatorExpression<>(jaxbAttrDes, attrFactory.getDatatype().getBagDatatype(), attributeProvider);
} else if (expr instanceof AttributeSelectorType)
}
else if (expr instanceof AttributeSelectorType)
{
if (!allowAttributeSelectors)
{
......@@ -579,26 +594,31 @@ public final class DepthLimitingExpressionFactory implements ExpressionFactory
}
expression = AttributeSelectorExpressions.newInstance(jaxbAttrSelector, xPathCompiler, attributeProvider, attrFactory);
} else if (expr instanceof AttributeValueType)
}
else if (expr instanceof AttributeValueType)
{
expression = getInstance((AttributeValueType) expr, xPathCompiler);
} else if (expr instanceof FunctionType)
}
else if (expr instanceof FunctionType)
{
final FunctionType jaxbFunc = (FunctionType) expr;
final FunctionExpression funcExp = getFunction(jaxbFunc.getFunctionId());
if (funcExp != null)
{
expression = funcExp;
} else
}
else
{
throw new IllegalArgumentException("Function " + jaxbFunc.getFunctionId()
+ " is not supported (at least) as standalone Expression: either a generic higher-order function supported only as Apply FunctionId, or function completely unknown.");
}
} else if (expr instanceof VariableReferenceType)
}
else if (expr instanceof VariableReferenceType)
{
final VariableReferenceType varRefElt = (VariableReferenceType) expr;
expression = getVariable(varRefElt, longestVarRefChain);
} else
}
else
{
throw new IllegalArgumentException("Expressions of type " + expr.getClass().getSimpleName()
+ " are not supported. Expected: one of Apply, AttributeDesignator, AttributeSelector, AttributeValue, Function or VariableReference.");
......
/**
* Copyright 2012-2018 Thales Services SAS.
*
* This file is part of AuthzForce CE.
*
* Licensed under 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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ow2.authzforce.core.pdp.impl.expression;
import java.util.Optional;
import org.ow2.authzforce.core.pdp.api.AttributeFqn;
import org.ow2.authzforce.core.pdp.api.AttributeFqns;
import org.ow2.authzforce.core.pdp.api.AttributeProvider;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.AttributeDesignatorExpression;
import org.ow2.authzforce.core.pdp.api.value.AttributeValue;
import org.ow2.authzforce.core.pdp.api.value.Bag;
import org.ow2.authzforce.core.pdp.api.value.BagDatatype;
import org.ow2.authzforce.core.pdp.api.value.Bags;
import org.ow2.authzforce.core.pdp.api.value.Datatype;
import org.ow2.authzforce.xacml.identifiers.XacmlStatusCode;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
/**
* AttributeDesignator evaluator initialized with and using an {@link AttributeProvider} to retrieve the attribute value not only from the request but also possibly from extra Attribute Provider
* modules (so-called XACML PIPs) (PDP extensions)
*
* @param <AV>
* AttributeDesignator evaluation result value's primitive datatype
*
* @version $Id: $
*/
public final class GenericAttributeProviderBasedAttributeDesignatorExpression<AV extends AttributeValue> implements AttributeDesignatorExpression<AV>
{
private static final IllegalArgumentException NULL_ATTRIBUTE_PROVIDER_EXCEPTION = new IllegalArgumentException("Undefined attribute Provider");
private final AttributeFqn attrGUID;
private final BagDatatype<AV> returnType;
private final boolean mustBePresent;
private final transient Bag.Validator mustBePresentEnforcer;
private final transient AttributeProvider attrProvider;
private final transient IndeterminateEvaluationException missingAttributeForUnknownReasonException;
private final transient IndeterminateEvaluationException missingAttributeBecauseNullContextException;
// lazy initialization
private transient volatile String toString = null;
private transient volatile int hashCode = 0;
/** {@inheritDoc} */
@Override
public Optional<Bag<AV>> getValue()
{
/*
* context-dependent, therefore not constant
*/
return Optional.empty();
}
/**
* Return an instance of an AttributeDesignator based on an AttributeDesignatorType
*
* @param attrDesignator
* the AttributeDesignatorType we want to convert
* @param resultDatatype
* expected datatype of the result of evaluating this AttributeDesignator ( {@code AV is the expected type of every element in the bag})
* @param attrProvider
* Attribute Provider responsible for finding the attribute designated by this in a given evaluation context at runtime
* @throws IllegalArgumentException
* if {@code attrDesignator.getCategory() == null || attrDesignator.getAttributeId() == null}
*/
public GenericAttributeProviderBasedAttributeDesignatorExpression(final AttributeDesignatorType attrDesignator, final BagDatatype<AV> resultDatatype, final AttributeProvider attrProvider)
{
if (attrProvider == null)
{
throw NULL_ATTRIBUTE_PROVIDER_EXCEPTION;
}
this.attrProvider = attrProvider;
this.attrGUID = AttributeFqns.newInstance(attrDesignator);
this.returnType = resultDatatype;
// error messages/exceptions
final String missingAttributeMessage = this + " not found in context";
this.mustBePresent = attrDesignator.isMustBePresent();
this.mustBePresentEnforcer = mustBePresent ? new Bags.NonEmptinessValidator(missingAttributeMessage) : Bags.DUMB_VALIDATOR;
this.missingAttributeForUnknownReasonException = new IndeterminateEvaluationException(missingAttributeMessage + " for unknown reason", XacmlStatusCode.MISSING_ATTRIBUTE.value());
this.missingAttributeBecauseNullContextException = new IndeterminateEvaluationException(
"Missing Attributes/Attribute for evaluation of AttributeDesignator '" + this.attrGUID + "' because request context undefined", XacmlStatusCode.MISSING_ATTRIBUTE.value());
}
@Override
public AttributeFqn getAttributeFQN()
{
return this.attrGUID;
}
@Override
public boolean isNonEmptyBagRequired()
{
return this.mustBePresent;
}
/**
* {@inheritDoc}
*
* Evaluates the pre-assigned meta-data against the given context, trying to find some matching values.
*/
@Override
public Bag<AV> evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
{
if (context == null)
{
throw missingAttributeBecauseNullContextException;
}
final Bag<AV> bag = attrProvider.get(attrGUID, this.returnType.getElementType(), context);
if (bag == null)
{
throw this.missingAttributeForUnknownReasonException;
}
mustBePresentEnforcer.validate(bag);
/*
* if we got here, it means that the bag wasn't empty, or bag was empty AND mustBePresent was false (so validate() succeeded), so we just return the result
*/
return bag;
}
/** {@inheritDoc} */
@Override
public Datatype<Bag<AV>> getReturnType()
{
return this.returnType;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
/** {@inheritDoc} */
@Override
public String toString()
{
if (toString == null)
{
toString = "AttributeDesignator [" + this.attrGUID + ", dataType= " + this.returnType.getElementType() + ", mustBePresent= "
+ (mustBePresentEnforcer == Bags.DUMB_VALIDATOR ? "false" : "true") + "]";
}
return toString;
}
/** {@inheritDoc} */
@Override
public int hashCode()
{
if (hashCode == 0)
{
hashCode = this.attrGUID.hashCode();
}
return hashCode;
}
/** Equal iff the Attribute Category/Issuer/Id are equal */
@Override
public boolean equals(final Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof GenericAttributeProviderBasedAttributeDesignatorExpression))
{
return false;
}
final GenericAttributeProviderBasedAttributeDesignatorExpression<?> other = (GenericAttributeProviderBasedAttributeDesignatorExpression<?>) obj;
return this.attrGUID.equals(other.attrGUID);
}
}
......@@ -66,18 +66,6 @@ final class TimeRangeComparisonFunction extends SingleParameterTypedFirstOrderFu
*/
private static final TimeZone DEFAULT_TZ = TimeZone.getDefault();
/**
* Set {@code cal}'s date to the same as {@code ref}'s date
*
* @param cal
* @param ref
*/
private static void setSameDate(final Calendar cal, final Calendar ref)
{
cal.set(Calendar.YEAR, ref.get(Calendar.YEAR));
cal.set(Calendar.DAY_OF_YEAR, ref.get(Calendar.DAY_OF_YEAR));
}
/**
* Evaluates the time-in-range function, which takes three <code>TimeAttributeValue</code> values. This function return true if the first value falls between the second and third values (ie.,
* on or after the second time and on or before the third time). If no time zone is specified for the second and/or third time value, then the timezone from the first time value is used. This
......@@ -114,12 +102,9 @@ final class TimeRangeComparisonFunction extends SingleParameterTypedFirstOrderFu
}
/*
* Use start time as reference for the day in time comparisons, so set the timeChecked day to the one of the start time
*/
setSameDate(calCheckedWhetherInRange, startCal);
/*
* Now we date does not matter in calendar comparison, we only compare times of the day so ignoring the date, the checked time of the day might be before the lower time bound but still be
* in range if considered this is the time on the next day. In this case, startCal is on day N, and calCheckedWhetherInRange on day N+1.
* Reminder: year/month/day of underlying Calendars in TimeValues are all set to DatatypeConstants.FIELD_UNDEFINED. So the date does not matter in calendar comparison, we only compare
* times of the day so ignoring the date, the checked time of the day might be before the lower time bound but still be in range if considered this is the time on the next day. In this
* case, startCal is on day N, and calCheckedWhetherInRange on day N+1.
*/
/*
* Boolean below says whether the checked time is strictly after the start time if considered on the *same day*, i.e. in terms of time of day.
......@@ -127,7 +112,7 @@ final class TimeRangeComparisonFunction extends SingleParameterTypedFirstOrderFu
final boolean isCheckedDayTimeStrictlyBeforeStartDayTime = calCheckedWhetherInRange.before(startCal);
if (startCal.after(endCal))
{
/**
/*
* start time of the day > end time of the day, for instance 02:00:00 > 01:00:00 so we consider the end time (01:00:00) on the next day (later than the second argument - end time - by
* less than 24h, the spec says). So we interpret the time interval as the date interval [startTime on day N, endTime on day N+1]. If checked time of day < start time of day (compared
* on the same day), then checked time can only be on day after to be in range
......@@ -135,14 +120,9 @@ final class TimeRangeComparisonFunction extends SingleParameterTypedFirstOrderFu
if (isCheckedDayTimeStrictlyBeforeStartDayTime)
{
/*
* time checked is strictly before start time if considered on the same day, so not in range unless considered on day N+1 So let's compared with end time after considering them on
* the same day
* Time checked is strictly before start time. If considered on the same day, it is not in range. Else considered on day N+1, ie same day as end time. So let's compare with end
* time. Time checked is in range if and only if before or equals end time (on day N+1), i.e. not strictly after
*/
// calCheckedWhetherInRange.add(Calendar.DAY_OF_YEAR, 1);
// set checked time to same day as end time for comparison
setSameDate(calCheckedWhetherInRange, endCal);
// time checked is in range if and only if before or equals end time (on day N+1),
// i.e. not strictly after
return !calCheckedWhetherInRange.after(endCal);
}
......@@ -152,18 +132,18 @@ final class TimeRangeComparisonFunction extends SingleParameterTypedFirstOrderFu
return true;
}
// start time <= end time -> all considered on the same day
/*
* Start time <= end time -> all considered on the same day
*/
if (isCheckedDayTimeStrictlyBeforeStartDayTime)
{
// checked time < start time -> out of range
return false;
}
// checked time >= start time
// set checked time to same day as end time for comparison
setSameDate(calCheckedWhetherInRange, endCal);
// time checked is in range if and only if before or equals end time, so not strictly after
/*
* Checked time >= start time. Time checked is in range if and only if before or equals end time, so not strictly after
*/
return !calCheckedWhetherInRange.after(endCal);
}
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-io-xacml-json</artifactId>
......@@ -41,7 +41,7 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-testutils</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-testutils</artifactId>
......@@ -23,7 +23,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-core-pdp-engine</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
......
......@@ -6,7 +6,7 @@
<version>7.3.0</version>
</parent>
<artifactId>authzforce-ce-core</artifactId>
<version>13.1.0</version>
<version>13.2.0</version>
<packaging>pom</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description>AuthzForce - XACML-compliant Core PDP Engine and associated test modules</description>
......@@ -33,7 +33,7 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-api</artifactId>
<version>15.1.0</version>
<version>15.2.0</version>
</dependency>
<!-- /AuthzForce dependencies -->
<!-- Test dependencies -->
......
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