Commit 48179e21 authored by cdanger's avatar cdanger

Merge branch 'release/6.0.0'

parents 4151a65e f5c4fb9d
......@@ -2,10 +2,36 @@
All notable changes to this project are documented in this file following the [Keep a CHANGELOG](http://keepachangelog.com) conventions.
## 6.0.0
### Added
- Extension mechanism to switch HashMap/HashSet implementation; default implementation is based on native JRE and Guava.
- Validation of 'n' argument (minimum of *true* arguments) of XACML 'n-of' function if this is constant (must be a positive integer not greater than the number of remaining arguments)
- Validation of second and third arguments of XACML substring function if these are constants (arg1 >= 0 && (arg2 == -1 || arg2 >= arg1))
- Maven plugin owasp-dependency-check to check vulnerabilities in dependencies
### Changed
- Maven parent project version: 3.4.0 -> 4.0.0:
- **Java version: 1.7 -> 1.8** (fixes GitHub issue #4)
- Guava dependency version: 18.0 -> 20.0
- Saxon-HE dependency version: 9.6.0-5 -> 9.7.0-11
- com.sun.mail:javax.mail v1.5.4 changed to com.sun.mail:mailapi v1.5.6
- Dependency authzforce-ce-core-pdp-api 7.1.1 -> 8.0.0
- Behavior of *unordered* rule combining algorithms (deny-overrides, permit-overrides, deny-unless-permit and permit-unless deny), i.e. for which the order of evaluation may be different from the order of declaration: child elements are re-ordered for more efficiency (e.g. Deny rules evaluated first in case of deny-overrides algorithm), therefore the algorithm implementation, the order of evaluation in particular, now differs from ordered-* variants.
### Removed
- Dependency on Koloboke, replaced by extension mechanism mentioned in *Added* section that would allow to switch from the default HashMap/HashSet implementation to Koloboke-based.
### Fixed
- OW2 #AUTHZFORCE-23: enforcement of RuleId/PolicyId/PolicySetId uniqueness:
- PolicyId (resp. PolicySetId) should be unique across all policies loaded by PDP so that PolicyIdReferences (resp. PolicySetIdReferences) in Responses' PolicyIdentifierList are absolute references to applicable policies (no ambiguity).
- [RuleId should be unique within a policy](https://lists.oasis-open.org/archives/xacml/201310/msg00025.html) -> A rule is globally uniquely identified by the parent PolicyId and the RuleId.
## 5.0.2
### Changed
- Dependency version: authzforce-core-pdp-api: 7.1.1 (was: 7.1.0)
## 5.0.1
### 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.
......
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/dee3e6f5cdd240fc80dfdcc1ee419ac8)](https://www.codacy.com/app/coder103/authzforce-ce-core?utm_source=github.com&utm_medium=referral&utm_content=authzforce/core&utm_campaign=Badge_Grade)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/389/badge)](https://bestpractices.coreinfrastructure.org/projects/389)
# AuthZForce PDP Core (Community Edition)
Authorization PDP (Policy Decision Point) engine implementing the [OASIS XACML v3.0](http://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html).
......@@ -30,15 +31,16 @@ Java projects may use AuthZForce Core to instantiate an embedded Java PDP.
* **Attribute Datatypes**: you may extend the PDP engine with custom XACML attribute datatypes;
* **Functions**: you may extend the PDP engine with custom XACML functions;
* **Combining Algorithms**: you may extend the PDP engine with custom XACML policy/rule combining algorithms;
* **Attribute Providers**: you may plug custom attribute providers into the PDP engine to allow it to retrieve attributes from other attribute sources (e.g. remote service) than the input XACML Request during evaluation;
* **Attribute Providers a.k.a. PIPs** (Policy Information Points): you may plug custom attribute providers into the PDP engine to allow it to retrieve attributes from other attribute sources (e.g. remote service) than the input XACML Request during evaluation;
* **Request Filter**: you may customize the processing of XACML Requests before evaluation by the PDP core engine (e.g. used for implementing [XACML v3.0 Multiple Decision Profile Version 1.0 - Repeated attribute categories](http://docs.oasis-open.org/xacml/3.0/multiple/v1.0/cs02/xacml-3.0-multiple-v1.0-cs02.html#_Toc388943334));
* **Result Filter**: you may customize the processing of XACML Results after evaluation by the PDP engine (e.g. used for implementing [XACML v3.0 Multiple Decision Profile Version 1.0 - Requests for a combined decision](http://docs.oasis-open.org/xacml/3.0/xacml-3.0-multiple-v1-spec-cd-03-en.html#_Toc260837890));
* **Root Policy Provider**: you may plug custom policy providers into the PDP engine to allow it to retrieve the root policy from specific sources (e.g. remote service);
* **Ref Policy Providers**: you may plug custom policy providers into the PDP engine to allow it to resolve `PolicyIdReference` or `PolicySetIdReference`;
* **Decision Cache**: you may extend the PDP engine with a custom XACML decision cache, allowing the PDP to skip evaluation and retrieve XACML decisions from cache for recurring XACML Requests;
* PIP (Policy Information Point): AuthzForce provides XACML PIP features in the form of extensions called *Attribute Providers*. More information in the previous list on *Extensibility points*.
## Versions
See the [change log file](CHANGELOG.md) according to the *Keep a CHANGELOG* [conventions](http://keepachangelog.com/).
See the [change log file](CHANGELOG.md) following the *Keep a CHANGELOG* [conventions](http://keepachangelog.com/).
## License
See the [license file](LICENSE.txt).
......@@ -53,16 +55,24 @@ If you want to use the experimental features (see previous section) as well, you
To get started using a PDP to evaluate XACML requests, instantiate a new PDP instance with one of the methods: `org.ow2.authzforce.core.pdp.impl.PdpConfigurationParser#getPDP(...)`. The parameters are:
1. Location of the configuration file (mandatory): this file must be an XML document compliant with the PDP configuration [XML schema](src/main/resources/pdp.xsd). You can read the documentation of every configuration parameter in that file.
1. Location of the XML catalog (optional, required only if using one or more XML-schema-defined PDP extensions): used to resolve the PDP configuration schema and other imported schemas/DTDs, and schemas of any PDP extension namespace used in the configuration file. You may use the [catalog](src/main/resources/catalog.xml) in the sources as an example. This is the one used by default if none specified.
1. Location of the PDP extensions schema file (optional, required only if using one or more PDP extensions): contains imports of namespaces corresponding to XML schemas of all XML-schema-defined PDP extensions to be used in the configuration file. Used for validation of PDP extensions configuration. The actual schema locations are resolved by the XML catalog parameter. You may use the [pdp-ext.xsd](src/test/resources/pdp-ext.xsd) in the sources as an example.
1. *confLocation*: location of the configuration file (mandatory): this file must be an XML document compliant with the PDP configuration [XML schema](src/main/resources/pdp.xsd). You can read the documentation of every configuration parameter in that file. If you don't use any XML-schema-defined PDP extension (AttributeProviders, PolicyProviders...), this is the only parameter you need, and you can use the simplest method `PdpConfigurationParser#getPDP(String confLocation)` to load your PDP. Here is an example of configuration:
Once you have a PDP instance. You can evaluate a XACML request by calling one of the `PDP#evaluate(...)` methods.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<pdp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://authzforce.github.io/core/xmlns/pdp/5.0" version="5.0.0">
<rootPolicyProvider id="rootPolicyProvider" xsi:type="StaticRootPolicyProvider" policyLocation="${PARENT_DIR}/policy.xml" />
</pdp>
```
This is a basic PDP configuration with basic settings and the root policy (XACML Policy document) loaded from a file `policy.xml` (see [this one](src/test/resources/conformance/xacml-3.0-from-2.0-ct/mandatory/IIA001/IIA001Policy.xml) for an example) located in the same directory as this PDP configuration file.
1. *catalogLocation*: location of the XML catalog (optional, required only if using one or more XML-schema-defined PDP extensions): used to resolve the PDP configuration schema and other imported schemas/DTDs, and schemas of any PDP extension namespace used in the configuration file. You may use the [catalog](src/main/resources/catalog.xml) in the sources as an example. This is the one used by default if none specified.
1. *extensionXsdLocation*: location of the PDP extensions schema file (optional, required only if using one or more XML-schema-defined PDP extensions): contains imports of namespaces corresponding to XML schemas of all XML-schema-defined PDP extensions to be used in the configuration file. Used for validation of PDP extensions configuration. The actual schema locations are resolved by the XML catalog parameter. You may use the [pdp-ext.xsd](src/test/resources/pdp-ext.xsd) in the sources as an example.
Once you have a instance of `PDP`, you can evaluate a XACML request by calling one of the `PDP#evaluate(...)` methods.
Our PDP implementation uses SLF4J for logging so you can use any SLF4J implementation to manage logging. As an example, we use logback for testing, so you can use [logback.xml](src/test/resources/logback.xml) as an example for configuring loggers, appenders, etc.
If you are using **Java 8**, make sure you set the following JVM system property is set before execution:
`javax.xml.accessExternalSchema = http`
If you are using **Java 8**, make sure the following JVM argument is set before execution:
`-Djavax.xml.accessExternalSchema=http`
## Support
......
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
<suppress>
<notes><![CDATA[
file name: mailapi-1.5.6.jar
]]></notes>
<gav regex="true">^com\.sun\.mail:mailapi:.*$</gav>
<cve>CVE-2007-6059</cve>
</suppress>
</suppressions>
\ No newline at end of file
......@@ -3,10 +3,10 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-parent</artifactId>
<version>3.4.0</version>
<version>4.0.0</version>
</parent>
<artifactId>authzforce-ce-core</artifactId>
<version>5.0.2</version>
<version>6.0.0</version>
<name>${project.groupId}:${project.artifactId}</name>
<description>AuthZForce Community Edition - XACML-compliant Core Engine</description>
<url>https://tuleap.ow2.org/projects/authzforce</url>
......@@ -35,7 +35,6 @@
<!-- For loading XML schemas with OASIS catalog (CatalogManager) -->
<groupId>xml-resolver</groupId>
<artifactId>xml-resolver</artifactId>
<version>1.2</version>
</dependency>
<!-- /Third-party dependencies -->
......@@ -43,7 +42,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-core-pdp-api</artifactId>
<version>7.1.1</version>
<version>8.0.0</version>
</dependency>
<!-- /Authzforce dependencies -->
......@@ -63,6 +62,22 @@
</dependencies>
<build>
<plugins>
<plugin>
<!-- Consider combining with Red Hat Victims and OSS Index. More info on Victims vs. Dependency-check: https://bugzilla.redhat.com/show_bug.cgi?id=1388712 -->
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<configuration>
<!-- The plugin has numerous issues with version matching, which triggers false positives so we need a "suppresion" file for those. More info: https://github.com/jeremylong/DependencyCheck/issues -->
<suppressionFile>owasp-dependency-check-suppression.xml</suppressionFile>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
......@@ -202,7 +217,6 @@
<!-- Test configuration -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>false</skipTests>
<systemPropertyVariables>
......@@ -216,7 +230,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
......
......@@ -21,14 +21,13 @@ package org.ow2.authzforce.core.pdp.impl;
import java.util.Map;
import java.util.Set;
import org.ow2.authzforce.core.pdp.api.HashCollections;
import org.ow2.authzforce.core.pdp.api.PdpExtension;
import org.ow2.authzforce.core.pdp.api.PdpExtensionRegistry;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import com.koloboke.collect.set.hash.HashObjSets;
/**
* This is a base implementation of <code>PdpExtensionRegistry</code>. This should be used as basis to implement (in a final class) an immutable PDP extension registry of a specific type. If you need
......@@ -58,7 +57,7 @@ public abstract class BasePdpExtensionRegistry<T extends PdpExtension> implement
assert extensionClass != null && extensionsById != null;
this.extClass = extensionClass;
this.extensionsById = HashObjObjMaps.newImmutableMap(extensionsById);
this.extensionsById = HashCollections.newImmutableMap(extensionsById);
this.toString = this + "( extensionClass= " + extClass.getCanonicalName() + " )";
}
......@@ -73,7 +72,7 @@ public abstract class BasePdpExtensionRegistry<T extends PdpExtension> implement
@Override
public final Set<T> getExtensions()
{
return HashObjSets.newImmutableSet(extensionsById.values());
return HashCollections.newImmutableSet(extensionsById.values());
}
private static final class ExtensionToIdFunction<E extends PdpExtension> implements Function<E, String>
......
......@@ -24,8 +24,14 @@ 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.HashCollections;
import org.ow2.authzforce.core.pdp.api.ImmutableIndividualDecisionRequest;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.IndividualDecisionRequest;
......@@ -36,13 +42,6 @@ import org.ow2.authzforce.core.pdp.api.StatusHelper;
import org.ow2.authzforce.core.pdp.api.value.Bag;
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 +51,8 @@ public final class DefaultRequestFilter extends BaseRequestFilter
{
/**
*
* Factory for this type of request filter that allows duplicate &lt;Attribute&gt; with same meta-data in the same
* &lt;Attributes&gt; element of a Request (complying with XACML 3.0 core spec, §7.3.3).
* Factory for this type of request filter that allows duplicate &lt;Attribute&gt; with same meta-data in the same &lt;Attributes&gt; element of a Request (complying with XACML 3.0 core spec,
* §7.3.3).
*
*/
public static final class LaxFilterFactory implements RequestFilter.Factory
......@@ -70,12 +69,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 +84,8 @@ public final class DefaultRequestFilter extends BaseRequestFilter
/**
*
* Factory for this type of request filter that does NOT allow duplicate &lt;Attribute&gt; with same meta-data in
* the same &lt;Attributes&gt; 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 &lt;Attribute&gt; with same meta-data in the same &lt;Attributes&gt; 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 +99,58 @@ 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<>();
final Map<AttributeGUID, Bag<?>> namedAttributes = HashCollections.newUpdatableMap(attributesList.size());
final Map<String, XdmNode> extraContentsByCategory = HashCollections.newUpdatableMap(attributesList.size());
/*
* 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());
/*
* 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)
final XdmNode newContentNode = categorySpecificAttributes.getExtraContent();
if (newContentNode != 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);
final XdmNode oldContentNode = extraContentsByCategory.put(categoryName, newContentNode);
/*
* 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 (oldContentNode != 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);
}
}
/*
* 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 +159,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));
}
}
......@@ -29,6 +29,7 @@ import net.sf.saxon.s9api.XdmNode;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.AttributeSelectorId;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.HashCollections;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.IndividualDecisionRequest;
import org.ow2.authzforce.core.pdp.api.StatusHelper;
......@@ -42,8 +43,6 @@ import org.ow2.authzforce.core.pdp.api.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.koloboke.collect.map.hash.HashObjObjMaps;
/**
* An {@link EvaluationContext} associated to an XACML Individual Decision Request, i.e. for evaluation to a single authorization decision Result (see Multiple Decision Profile spec for more
* information on Individual Decision Request as opposed to Multiple Decision Request).
......@@ -59,9 +58,9 @@ public final class IndividualDecisionRequestContext implements EvaluationContext
private final Map<AttributeGUID, Bag<?>> namedAttributes;
private final Map<String, Value> varValsById = HashObjObjMaps.newMutableMap();
private final Map<String, Value> varValsById = HashCollections.newMutableMap();
private final Map<String, Object> mutableProperties = HashObjObjMaps.newMutableMap();
private final Map<String, Object> mutableProperties = HashCollections.newMutableMap();
/*
* Corresponds to Attributes/Content (by attribute category) marshalled to XPath data model for XPath evaluation: AttributeSelector evaluation, XPath-based functions, etc. This may be empty if no
......@@ -99,7 +98,7 @@ public final class IndividualDecisionRequestContext implements EvaluationContext
public IndividualDecisionRequestContext(final Map<AttributeGUID, Bag<?>> namedAttributeMap, final Map<String, XdmNode> extraContentsByAttributeCategory,
final boolean returnApplicablePolicyIdList, final boolean returnUsedAttributes)
{
this.namedAttributes = namedAttributeMap == null ? HashObjObjMaps.<AttributeGUID, Bag<?>> newUpdatableMap() : namedAttributeMap;
this.namedAttributes = namedAttributeMap == null ? HashCollections.<AttributeGUID, Bag<?>> newUpdatableMap() : namedAttributeMap;
this.returnApplicablePolicyIdList = returnApplicablePolicyIdList;
this.usedNamedAttributeIdSet = returnUsedAttributes ? UpdatableCollections.<AttributeGUID> newUpdatableSet() : UpdatableCollections.<AttributeGUID> emptySet();
if (extraContentsByAttributeCategory == null)
......
......@@ -21,42 +21,38 @@ package org.ow2.authzforce.core.pdp.impl;
import java.util.Arrays;
import java.util.List;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Match;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
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.func.Function;
import org.ow2.authzforce.core.pdp.api.func.FunctionCall;
import org.ow2.authzforce.core.pdp.api.value.AttributeValue;
import org.ow2.authzforce.core.pdp.api.value.BooleanValue;
import org.ow2.authzforce.core.pdp.impl.func.StandardFunction;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Match;
/**
* XACML Match evaluator. This is the part of the Target that actually evaluates
* whether the specified attribute values in the Target match the corresponding
* attribute values in the request context.
* XACML Match evaluator. This is the part of the Target that actually evaluates whether the specified attribute values in the Target match the corresponding attribute values in the request context.
*
* @version $Id: $
*/
public final class MatchEvaluator
{
private static final IllegalArgumentException NULL_XACML_MATCH_ARGUMENT_EXCEPTION = new IllegalArgumentException(
"Undefined input XACML Match element");
private static final IllegalArgumentException NULL_XACML_EXPRESSION_FACTORY_ARGUMENT_EXCEPTION = new IllegalArgumentException(
"Undefined input XACML Expression parser");
private static final IllegalArgumentException NULL_XACML_MATCH_ARGUMENT_EXCEPTION = new IllegalArgumentException("Undefined input XACML Match element");
private static final IllegalArgumentException NULL_XACML_EXPRESSION_FACTORY_ARGUMENT_EXCEPTION = new IllegalArgumentException("Undefined input XACML Expression parser");
/**
* Any-of function call equivalent to this Match:
* <p>
* Match(matchFunction, attributeValue, bagExpression) =
* anyOf(matchFunction, attributeValue, bagExpression)
* Match(matchFunction, attributeValue, bagExpression) = anyOf(matchFunction, attributeValue, bagExpression)
*/
private final transient FunctionCall<BooleanValue> anyOfFuncCall;
......@@ -68,13 +64,11 @@ public final class MatchEvaluator
* @param expFactory
* bagExpression factory
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default
* XPath version
* XPath compiler corresponding to enclosing policy(set) default XPath version
* @throws java.lang.IllegalArgumentException
* null {@code expFactory} or null/empty {@code jaxbMatch}
*/
public MatchEvaluator(final Match jaxbMatch, final XPathCompiler xPathCompiler, final ExpressionFactory expFactory)
throws IllegalArgumentException
public MatchEvaluator(final Match jaxbMatch, final XPathCompiler xPathCompiler, final ExpressionFactory expFactory) throws IllegalArgumentException
{
if (jaxbMatch == null)
{
......@@ -89,7 +83,7 @@ public final class MatchEvaluator
// get the matchFunction type, making sure that it's really a correct
// Target matchFunction
final String matchId = jaxbMatch.getMatchId();
final Function<?> matchFunction = expFactory.getFunction(matchId);
final FunctionExpression matchFunction = expFactory.getFunction(matchId);
if (matchFunction == null)
{
throw new IllegalArgumentException("Unsupported function for MatchId: " + matchId);
......@@ -99,8 +93,7 @@ public final class MatchEvaluator
// value paired with it
final AttributeDesignatorType attributeDesignator = jaxbMatch.getAttributeDesignator();
final AttributeSelectorType attributeSelector = jaxbMatch.getAttributeSelector();
final Expression<?> bagExpression = expFactory.getInstance(
attributeDesignator == null ? attributeSelector : attributeDesignator, xPathCompiler, null);
final Expression<?> bagExpression = expFactory.getInstance(attributeDesignator == null ? attributeSelector : attributeDesignator, xPathCompiler, null);
final AttributeValueType attributeValue = jaxbMatch.getAttributeValue();
final Expression<? extends AttributeValue> attrValueExpr;
......@@ -113,42 +106,35 @@ public final class MatchEvaluator
throw new IllegalArgumentException("Invalid <Match>'s <AttributeValue>", e);
}
// Match(matchFunction, attributeValue, bagExpression) =
// anyOf(matchFunction,
// attributeValue, bagExpression)
final Function<BooleanValue> anyOfFunc = (Function<BooleanValue>) expFactory
.getFunction(StandardFunction.ANY_OF.getId());
if (anyOfFunc == null)
/*
* Match(matchFunction, attributeValue, bagExpression) = anyOf(matchFunction, attributeValue, bagExpression)
*/
final FunctionExpression funcExp = expFactory.getFunction(StandardFunction.ANY_OF.getId());
if (funcExp == null)
{
throw new IllegalArgumentException(
"Unsupported function '" + StandardFunction.ANY_OF.getId() + "' required for Match evaluation");
throw new IllegalArgumentException("Unsupported function '" + StandardFunction.ANY_OF.getId() + "' required for Match evaluation");
}
final List<Expression<?>> anyOfFuncInputs = Arrays.<Expression<?>> asList(matchFunction, attrValueExpr,
bagExpression);
final Function<BooleanValue> anyOfFunc = funcExp.getValue();
final List<Expression<?>> anyOfFuncInputs = Arrays.<Expression<?>> asList(matchFunction, attrValueExpr, bagExpression);
try
{
this.anyOfFuncCall = anyOfFunc.newCall(anyOfFuncInputs);
}
catch (final IllegalArgumentException e)
{
throw new IllegalArgumentException(
"Invalid inputs (Expressions) to the Match (validated using the equivalent standard 'any-of' function definition): "
+ anyOfFuncInputs,
e);
throw new IllegalArgumentException("Invalid inputs (Expressions) to the Match (validated using the equivalent standard 'any-of' function definition): " + anyOfFuncInputs, e);
}
}
/**
* Determines whether this <code>Match</code> matches the input request
* (whether it is applicable)
* Determines whether this <code>Match</code> matches the input request (whether it is applicable)
*
* @param context
* the evaluation context
* @return true iff the context matches
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* error occurred evaluating the Match element in this
* evaluation {@code context}
* error occurred evaluating the Match element in this evaluation {@code context}
*/
public boolean match(final EvaluationContext context) throws IndeterminateEvaluationException
{
......@@ -159,8 +145,7 @@ public final class MatchEvaluator
}
catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException("Error evaluating Match (with equivalent 'any-of' function)",
e.getStatusCode(), e);
throw new IndeterminateEvaluationException("Error evaluating Match (with equivalent 'any-of' function)", e.getStatusCode(), e);
}
return anyOfFuncCallResult.getUnderlyingValue().booleanValue();
......
......@@ -23,16 +23,15 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.HashCollections;
import org.ow2.authzforce.core.pdp.api.IndividualDecisionRequest;
import org.ow2.authzforce.core.pdp.api.SingleCategoryAttributes;
import org.ow2.authzforce.core.pdp.api.value.Bag;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import net.sf.saxon.s9api.XdmNode;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attributes;
/**
* Mutable Individual Decision Request
*
......@@ -40,10 +39,8 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attributes;
*/
public final class MutableIndividualDecisionRequest implements IndividualDecisionRequest
{
private static final IllegalArgumentException UNDEF_ATTRIBUTES_EXCEPTION = new IllegalArgumentException(