Commit aba077c0 authored by cdanger's avatar cdanger

Merge branch 'release/9.0.0'

parents 85438979 50cffaf2
......@@ -6,3 +6,4 @@
/.pmd
/.pmdruleset.xml
/.project
/.checkstyle
......@@ -4,6 +4,28 @@ All notable changes to this project are documented in this file following the [K
Issues reported on [GitHub](https://github.com/authzforce/core/issues) are referenced in the form of `[GH-N]`, where N is the issue number. Issues reported on [OW2](https://jira.ow2.org/browse/AUTHZFORCE/) are mentioned in the form of `[OW2-N]`, where N is the issue number.
## Unreleased
### Changed
- Version of parent project: 6.0.0:
- The XML schema definition of PDP Decision Cache extensions' base type have been simplified (a few attributes removed).
- Version of dependency authzforce-ce-core-pdp-api: 11.0.0 (API changes):
- Changed PDPEngine interface methods
- Changed PDP extensions' interface methods: DecisionResultFilter, RequestFilter, DecisionCache (new EvaluationContext parameter to enable context-dependent caches), RefPolicyProvider (renamed RefPolicyProvider.Utils class to RefPolicyProvider.Helper).
- Changed EvaluationContext interface methods:
- Use of Bag replaced with AttributeBag class (AttributeBags are Bags with extra metadata such as the source - AttributeSource - of the attribute values: request, PDP, attribute provider extension, etc.
- New methods to help PDP extensions to watch for changes to the context with listeners
- Changed Expression interface methods
- Changed VersionPatterns class methods to return new PolicyVersionPattern class that helps manipulate XACML VersionMatchTypes
- Renamed class IndividualDecisionRequest to IndividualXACMLRequest (XACML-specific model of Individual Decision Request)
- Renamed class IndividualPdpDecisionRequest to PdpDecisionRequest (individual request in XACML-agnostic AuthzForce model)
- Renamed class AttributeGUID(s) to AttributeFQN(s) (Fully Qualified Name is more appropriate than GUID)
- Renamed class MutableBag to MutableAttributeBag
- Aded BaseStaticRefPolicyProviderModule class as convenient base class for implementing static Policy Provider (StaticRefPolicyProviderModule) implementations
### Added
- [PolicyProvider implementation](pdp-testutils/src/main/java/org/ow2/authzforce/core/pdp/testutil/ext/MongoDBRefPolicyProviderModule.java) for testing and documentation purposes, using MongoDB as policy database system and Jongo as client library, with [JUnit test class](pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/MongoDBRefPolicyProviderModuleTest.java) showing how to use it.
## 8.0.0
### Changed
- Version of parent project: 5.1.0
......@@ -192,14 +214,14 @@ Issues reported on [GitHub](https://github.com/authzforce/core/issues) are refer
## 3.6.0
### Added
- Support all [XACML 3.0 conformance tests](https://lists.oasis-open.org/archives/xacml-comment/201404/msg00001.html) published by AT&T on XACML mailing list in March 2014, except IIA010, IIA012, IIA024, IID029, IID030, III.C.2, III.C.3, IIIE301, IIIE303, II.G.2-6 (see also [README](src\test\resources\conformance\xacml-3.0-from-2.0-ct\README.md) ); with specific adaptations and enhancements:
- Support all [XACML 3.0 conformance tests](https://lists.oasis-open.org/archives/xacml-comment/201404/msg00001.html) published by AT&T on XACML mailing list in March 2014, except IIA010, IIA012, IIA024, IID029, IID030, III.C.2, III.C.3, IIIE301, IIIE303, II.G.2-6 (see also [README](pdp-testutils/src/test/resources/conformance/xacml-3.0-from-2.0-ct/README.md) ); with specific adaptations and enhancements:
1. XACML 3.0 Schema validation in all conformance tests (original files are not all compliant with XACML 3.0).
1. The original conformance test folder contains hundreds of files; for better readability and management, the folder is split in *mandatory* folder for tests on supported mandatory features (XACMl 3.0 core), *optional* folder for supported optional features (XACML 3.0 core and profiles), and *unsupported* for unsupported features.
1. For tests requiring a custom attribute finder, added a file with suffix `AttributeProvider.xml` that configures the `TestAttributeProviderModule`. This configuration file must contain a list of `Attributes` elements defining the attributes that this attribute provider is able to provide, with their constant values.
1. For tests requiring policies to be referenced via Policy(Set)IdReferences, added a directory named `refPolicies` containing a XACML Policy(Set) file per referenced Policy(Set).
1. For tests of Request syntax validation (syntax error expected to be detected by Authzforce PDP at initialization-time, i.e. before any Request evaluation), added suffix `.ignore` to the original test Policy(Set) and Response files.
1. For tests of Policy(Set) syntax validation (syntax error expected to be detected by Authzforce PDP at initialization-time, i.e. before any Request evaluation), added suffix `.ignore` to the original test Request and Response files.
- [HTML description](\src\test\resources\conformance\xacml-3.0-from-2.0-ct\ConformanceTests.html) of XACML 3.0 conformance tests
- [HTML description](pdp-testutils/src/test/resources/conformance/xacml-3.0-from-2.0-ct/ConformanceTests.html) of XACML 3.0 conformance tests
- Support of Policy(Set)Version in Policy(Set)IdReference handled by the native policy finder
- Support for Variable evaluation in Policy with scope management (variable is local to Policy where defined and inherited by Rules)
- Added support of xpathExpressions (optional XACML feature) in Request with support of namespace-prefix mappings extracted from XML document (XACML Request/Policy(Set)/Rule) (typically via `xmlns` declarations) where the xpathExpression is defined, e.g. XACML Request or Policy(Set).
......@@ -222,7 +244,7 @@ Issues reported on [GitHub](https://github.com/authzforce/core/issues) are refer
### Fixed
- Issues reported by PMD and findbugs
- Fixed issues in [XACML 3.0 conformance tests](https://lists.oasis-open.org/archives/xacml-comment/201404/msg00001.html) published by AT&T on XACML mailing list in March 2014, see [README](src\test\resources\conformance\xacml-3.0-from-2.0-ct\README.md).
- Fixed issues in [XACML 3.0 conformance tests](https://lists.oasis-open.org/archives/xacml-comment/201404/msg00001.html) published by AT&T on XACML mailing list in March 2014, see [README](pdp-testutils/src/test/resources/conformance/xacml-3.0-from-2.0-ct\README.md).
- In logical OR, AND and N-OF functions, an Indeterminate argument results in Indeterminate result.
1. FIX for OR function: If at least one True argument, return True regardless of Indeterminate arguments; else (no True) if there is at least one Indeterminate, return Indeterminate, return Indeterminate; else (no True/Indeterminate -> all false) return false
1. FIX for AND function: If at least one False argument, return False regardless of Indeterminate arguments; else (no False) if there is at least one Indeterminate, return Indeterminate, return Indeterminate; else (no False/Indeterminate -> all true) return true
......
......@@ -6,7 +6,7 @@ Authorization PDP (Policy Decision Point) engine implementing the [OASIS XACML v
Java projects may use AuthZForce Core to instantiate an embedded Java PDP.
*If you are interested in using a XACML PDP/PAP as a server with a RESTful API, go to the [AuthZForce server project](http://github.com/authzforce/server).*
*If you are interested in using the HTTP/REST API, go to the [AuthZForce server project](http://github.com/authzforce/server).*
## Features
* Compliance with the following OASIS XACML 3.0 standards:
......@@ -21,7 +21,7 @@ Java projects may use AuthZForce Core to instantiate an embedded Java PDP.
* [XACML 3.0 Additional Combining Algorithms Profile Version 1.0](http://docs.oasis-open.org/xacml/xacml-3.0-combalgs/v1.0/xacml-3.0-combalgs-v1.0.html): `on-permit-apply-second` policy combining algorithm;
* [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) (`urn:oasis:names:tc:xacml:3.0:profile:multiple:combined-decision`).
*For further details on what is actually supported with regards to the XACML specifications, please refer to the conformance tests [README](src/test/resources/conformance/xacml-3.0-from-2.0-ct/README.md).*
*For further details on what is actually supported with regards to the XACML specifications, please refer to the conformance tests [README](pdp-testutils/src/test/resources/conformance/xacml-3.0-from-2.0-ct/README.md).*
* Detection of circular XACML policy references (PolicyIdReference/PolicySetIdReference);
* Control of the **maximum XACML PolicyIdReference/PolicySetIdReference depth**;
* Control of the **maximum XACML VariableReference depth**;
......@@ -44,19 +44,23 @@ Java projects may use AuthZForce Core to instantiate an embedded Java PDP.
See the [change log file](CHANGELOG.md) following the *Keep a CHANGELOG* [conventions](http://keepachangelog.com/).
## License
See the [license file](LICENSE.txt).
See the [license file](LICENSE).
## Getting started
## Usage
### Getting started
You can either build Authzforce PDP library from the source code after cloning this git repository, or use the latest release from Maven Central with this information:
* groupId: `org.ow2.authzforce`;
* artifactId: `authzforce-ce-core`;
* artifactId: `authzforce-ce-core-pdp-engine`;
* packaging: `jar`.
If you want to use the experimental features (see previous section) as well, you need to use an extra Maven dependency that has the same groupId/artifactId/packaging but a specific classifier: `tests`.
If you want to use the experimental features (see previous section) as well, you need to use an extra Maven dependency:
* groupId: `org.ow2.authzforce`;
* artifactId: `authzforce-ce-core-pdp-testutils`;
* packaging: `jar`.
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.BasePdpEngine#getInstance(...)`. The parameters are:
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 `BasePdpEngine#getInstance(String confLocation)` to load your PDP. Here is an example of configuration:
1. *confLocation*: location of the configuration file (mandatory): this file must be an XML document compliant with the PDP configuration [XML schema](pdp-engine/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 `BasePdpEngine#getInstance(String confLocation)` to load your PDP. Here is an example of configuration:
```xml
<?xml version="1.0" encoding="UTF-8"?>
......@@ -64,21 +68,23 @@ To get started using a PDP to evaluate XACML requests, instantiate a new PDP ins
<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.
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](pdp-testutils/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](pdp-engine/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](pdp-testutils/src/test/resources/pdp-ext.xsd) in the sources as an example.
As a result of `getInstance(...)`, you get an instance of `BasePdpEngine` with which you can evaluate a XACML Request directly by calling the `evaluate(Request...)` methods; or you can evaluate a decision request (more precisely an equivalent of a Individual Decision Request as defined by the XACML Multiple Decision Profile) in AuthzForce's more efficient native model by calling `evaluate(ImmutablePdpDecisionRequest)` or (multiple decision requests with `evaluate(List<ImmutablePdpDecisionRequest>)`). In order to build a `ImmutablePdpDecisionRequest`, you may use the request builder returned by `BasePdpEngine#newRequestBuilder(...)`. Please look at the Javadoc for more information.
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.
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](pdp-testutils/src/test/resources/logback.xml) as an example for configuring loggers, appenders, etc.
If you are using **Java 8**, make sure the following JVM argument is set before execution:
`-Djavax.xml.accessExternalSchema=http`
## Example of usage and code with a web service authorization module
For an example of using an AuthzForce PDP engine in a real-life use case, please refer to the JUnit test class [LocalPdpAuthorizationTest](src/test/java/org/ow2/authzforce/core/pdp/impl/test/cxf/LocalPdpAuthorizationTest.java) and the Apache CXF authorization interceptor [LocalPdpBasedAuthzInterceptor](src/test/java/org/ow2/authzforce/core/pdp/impl/test/cxf/LocalPdpBasedAuthzInterceptor.java). The test class runs a test similar to @coheiga's [XACML 3.0 Authorization Interceptor test](https://github.com/coheigea/testcases/blob/master/apache/cxf/cxf-sts-xacml/src/test/java/org/apache/coheigea/cxf/sts/xacml/authorization/xacml3/XACML3AuthorizationTest.java) but using AuthzForce as PDP engine instead of OpenAZ. In this test, a web service client requests a Apache-CXF-based web service with a SAML token as credentials (previously issued by a Security Token Service upon successful client authentication) that contains the user ID and roles. Each request is intercepted on the web service side by a [CXF interceptor](src/test/java/org/ow2/authzforce/core/pdp/impl/test/cxf/LocalPdpBasedAuthzInterceptor.java) that plays the role of PEP (Policy Enforcement Point in XACML jargon), i.e. it extracts the various authorization attributes (user ID and roles, web service name, operation...) and requests a decision from a local PDP with these attributes, then enforces the PDP's decision, i.e. forwards the request to the web service implementation if the decision is Permit, else rejects it.
For more information, see the Javadoc of [LocalPdpAuthorizationTest](src/test/java/org/ow2/authzforce/core/pdp/impl/test/cxf/LocalPdpAuthorizationTest.java).
### Example of usage and PEP code with a web service authorization module
For an example of using an AuthzForce PDP engine in a real-life use case, please refer to the JUnit test class [EmbeddedPdpBasedAuthzInterceptorTest](pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/pep/cxf/EmbeddedPdpBasedAuthzInterceptorTest.java) and the Apache CXF authorization interceptor [EmbeddedPdpBasedAuthzInterceptor](pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/pep/cxf/EmbeddedPdpBasedAuthzInterceptor.java). The test class runs a test similar to @coheigea's [XACML 3.0 Authorization Interceptor test](https://github.com/coheigea/testcases/blob/master/apache/cxf/cxf-sts-xacml/src/test/java/org/apache/coheigea/cxf/sts/xacml/authorization/xacml3/XACML3AuthorizationTest.java) but using AuthzForce as PDP engine instead of OpenAZ. In this test, a web service client requests a Apache-CXF-based web service with a SAML token as credentials (previously issued by a Security Token Service upon successful client authentication) that contains the user ID and roles. Each request is intercepted on the web service side by a [EmbeddedPdpBasedAuthzInterceptor](pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/pep/cxf/EmbeddedPdpBasedAuthzInterceptor.java) that plays the role of PEP (Policy Enforcement Point in XACML jargon), i.e. it extracts the various authorization attributes (user ID and roles, web service name, operation...) and requests a decision from a local PDP with these attributes, then enforces the PDP's decision, i.e. forwards the request to the web service implementation if the decision is Permit, else rejects it.
For more information, see the Javadoc of [EmbeddedPdpBasedAuthzInterceptorTest](pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/pep/cxf/EmbeddedPdpBasedAuthzInterceptorTest.java).
## Extensions
If you are missing features in AuthzForce, you can extend it with various types of plugins (without changing the existing code), as described on the [wiki](../../wiki/Extensions).
## Support
......@@ -92,3 +98,6 @@ Please include as much information as possible; the more we know, the better the
* Your code & configuration files are often useful.
If you wish to contact the developers for other reasons, use [AuthzForce contact mailing list](http://scr.im/azteam).
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>8.0.0</version>
<version>9.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-engine</artifactId>
......@@ -42,7 +42,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-core-pdp-api</artifactId>
<version>9.1.0</version>
<version>11.0.0</version>
</dependency>
<!-- /Authzforce dependencies -->
......
......@@ -76,8 +76,8 @@ public final class AttributeAssignmentExpressionEvaluator
final XPathCompiler xPathCompiler, final ExpressionFactory expFactory) throws IllegalArgumentException
{
/*
* Cannot used AttributeGUID class to handle metadata because AttributeAssignment Category is not required like
* in AttributeDesignator which is what the AttributeGUID is used for
* Cannot used AttributeFQN class to handle metadata because AttributeAssignment Category is not required like
* in AttributeDesignator which is what the AttributeFQN is used for
*/
this.attributeId = Preconditions.checkNotNull(jaxbAttrAssignExp.getAttributeId(),
"Undefined AttributeAssignment/AttributeId");
......
......@@ -26,7 +26,8 @@ import java.util.Set;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
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.AttributeProviderModule;
import org.ow2.authzforce.core.pdp.api.CloseableAttributeProviderModule;
......@@ -113,7 +114,7 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
// not-null
private final Set<ModuleAdapter> moduleClosers;
private CloseableAttributeProvider(final Map<AttributeGUID, AttributeProviderModule> modulesByAttributeId, final Set<ModuleAdapter> moduleClosers, final boolean strictAttributeIssuerMatch)
private CloseableAttributeProvider(final Map<AttributeFQN, AttributeProviderModule> modulesByAttributeId, final Set<ModuleAdapter> moduleClosers, final boolean strictAttributeIssuerMatch)
{
super(modulesByAttributeId, null, strictAttributeIssuerMatch);
assert moduleClosers != null;
......@@ -121,7 +122,7 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
}
private static final CloseableAttributeProvider EVALUATION_CONTEXT_ONLY_SCOPED_CLOSEABLE_ATTRIBUTE_PROVIDER = new CloseableAttributeProvider(
Collections.<AttributeGUID, AttributeProviderModule> emptyMap(), Collections.<ModuleAdapter> emptySet(), true);
Collections.<AttributeFQN, AttributeProviderModule> emptyMap(), Collections.<ModuleAdapter> emptySet(), true);
/**
* Instantiates attribute Provider that tries to find attribute values in evaluation context, then, if not there, query the {@code module} providing the requested attribute ID, if any.
......@@ -153,7 +154,7 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
return EVALUATION_CONTEXT_ONLY_SCOPED_CLOSEABLE_ATTRIBUTE_PROVIDER;
}
final Map<AttributeGUID, AttributeProviderModule> modulesByAttributeId = HashCollections.newUpdatableMap();
final Map<AttributeFQN, AttributeProviderModule> modulesByAttributeId = HashCollections.newUpdatableMap();
final int moduleCount = jaxbAttributeProviderConfs.size();
final Set<ModuleAdapter> mutableModuleCloserSet = HashCollections.newUpdatableSet(moduleCount);
for (final AbstractAttributeProvider jaxbAttributeProviderConf : jaxbAttributeProviderConfs)
......@@ -176,8 +177,8 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
}
else
{
final Map<AttributeGUID, AttributeProviderModule> immutableCopyOfAttrProviderModsByAttrId = Collections
.<AttributeGUID, AttributeProviderModule> unmodifiableMap(modulesByAttributeId);
final Map<AttributeFQN, AttributeProviderModule> immutableCopyOfAttrProviderModsByAttrId = Collections
.<AttributeFQN, AttributeProviderModule> unmodifiableMap(modulesByAttributeId);
depAttrProvider = new ModularAttributeProvider(immutableCopyOfAttrProviderModsByAttrId, requiredAttrs, strictAttributeIssuerMatch);
}
......@@ -188,7 +189,7 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
for (final AttributeDesignatorType attrDesignator : moduleAdapter.getProvidedAttributes())
{
final AttributeGUID attrGUID = new AttributeGUID(attrDesignator);
final AttributeFQN attrGUID = AttributeFQNs.newInstance(attrDesignator);
final AttributeProviderModule duplicate = modulesByAttributeId.putIfAbsent(attrGUID, moduleAdapter.getAdaptedModule());
if (duplicate != null)
{
......
......@@ -28,19 +28,22 @@ 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.AttributeFQN;
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.ImmutablePdpDecisionRequest;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.IndividualDecisionRequest;
import org.ow2.authzforce.core.pdp.api.IndividualXACMLRequest;
import org.ow2.authzforce.core.pdp.api.JaxbXACMLUtils.JaxbXACMLAttributesParser;
import org.ow2.authzforce.core.pdp.api.PdpDecisionRequestFactory;
import org.ow2.authzforce.core.pdp.api.RequestFilter;
import org.ow2.authzforce.core.pdp.api.SingleCategoryAttributes;
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.AttributeBag;
import org.ow2.authzforce.core.pdp.api.value.DatatypeFactoryRegistry;
import com.google.common.collect.ImmutableList;
/**
* Default Request filter for Individual Decision Requests only (no support of Multiple Decision Profile in particular)
*
......@@ -48,6 +51,17 @@ import org.ow2.authzforce.core.pdp.api.value.DatatypeFactoryRegistry;
*/
public final class DefaultRequestFilter extends BaseRequestFilter
{
private static final PdpDecisionRequestFactory<ImmutablePdpDecisionRequest> DEFAULT_REQUEST_FACTORY = new PdpDecisionRequestFactory<ImmutablePdpDecisionRequest>()
{
@Override
public ImmutablePdpDecisionRequest getInstance(final Map<AttributeFQN, AttributeBag<?>> namedAttributes, final Map<String, XdmNode> extraContentsByCategory,
final boolean returnApplicablePolicies)
{
return ImmutablePdpDecisionRequest.getInstance(namedAttributes, extraContentsByCategory, returnApplicablePolicies);
}
};
/**
*
* 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,
......@@ -71,7 +85,7 @@ public final class DefaultRequestFilter extends BaseRequestFilter
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, DEFAULT_REQUEST_FACTORY, strictAttributeIssuerMatch, true, requireContentForXPath, xmlProcessor);
}
/**
......@@ -101,22 +115,42 @@ public final class DefaultRequestFilter extends BaseRequestFilter
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, DEFAULT_REQUEST_FACTORY, strictAttributeIssuerMatch, false, requireContentForXPath, xmlProcessor);
}
}
private DefaultRequestFilter(final DatatypeFactoryRegistry datatypeFactoryRegistry, final boolean strictAttributeIssuerMatch, final boolean allowAttributeDuplicates,
final boolean requireContentForXPath, final Processor xmlProcessor)
private final PdpDecisionRequestFactory<ImmutablePdpDecisionRequest> reqFactory;
/**
* Creates instance of default request filter
*
* @param datatypeFactoryRegistry
* attribute datatype registry
* @param requestFactory
* decision request factory
* @param strictAttributeIssuerMatch
* true iff strict attribute Issuer match must be enforced (in particular request attributes with empty Issuer only match corresponding AttributeDesignators with empty Issuer)
* @param allowAttributeDuplicates
* true iff duplicate Attribute (with same metadata) elements in Request (for multi-valued attributes) must be allowed
* @param requireContentForXPath
* true iff Content elements must be parsed, else ignored
* @param xmlProcessor
* XML processor for parsing Content elements iff {@code requireContentForXPath}
*/
public DefaultRequestFilter(final DatatypeFactoryRegistry datatypeFactoryRegistry, final PdpDecisionRequestFactory<ImmutablePdpDecisionRequest> requestFactory,
final boolean strictAttributeIssuerMatch, final boolean allowAttributeDuplicates, final boolean requireContentForXPath, final Processor xmlProcessor)
{
super(datatypeFactoryRegistry, strictAttributeIssuerMatch, allowAttributeDuplicates, requireContentForXPath, xmlProcessor);
assert requestFactory != null;
reqFactory = requestFactory;
}
/** {@inheritDoc} */
@Override
public List<? extends IndividualDecisionRequest> filter(final List<Attributes> attributesList, final JaxbXACMLAttributesParser xacmlAttrsParser, final boolean isApplicablePolicyIdListReturned,
public List<? extends IndividualXACMLRequest> 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 = HashCollections.newUpdatableMap(attributesList.size());
final Map<AttributeFQN, AttributeBag<?>> namedAttributes = HashCollections.newUpdatableMap(attributesList.size());
final Map<String, XdmNode> extraContentsByCategory = HashCollections.newUpdatableMap(attributesList.size());
/*
* attributesToIncludeInResult.size() <= attributesList.size()
......@@ -153,7 +187,7 @@ public final class DefaultRequestFilter extends BaseRequestFilter
* "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>
*/
for (final Entry<AttributeGUID, Bag<?>> attrEntry : categorySpecificAttributes)
for (final Entry<AttributeFQN, AttributeBag<?>> attrEntry : categorySpecificAttributes)
{
namedAttributes.put(attrEntry.getKey(), attrEntry.getValue());
}
......@@ -165,6 +199,7 @@ public final class DefaultRequestFilter extends BaseRequestFilter
}
}
return Collections.singletonList(new ImmutableIndividualDecisionRequest(namedAttributes, extraContentsByCategory, attributesToIncludeInResult, isApplicablePolicyIdListReturned));
return Collections.singletonList(new IndividualXACMLRequest(reqFactory.getInstance(namedAttributes, extraContentsByCategory, isApplicablePolicyIdListReturned), ImmutableList
.copyOf(attributesToIncludeInResult)));
}
}
/**
* Copyright 2012-2017 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;
import java.util.Map;
import net.sf.saxon.s9api.XdmNode;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.HashCollections;
import org.ow2.authzforce.core.pdp.api.IndividualPdpDecisionRequest;
import org.ow2.authzforce.core.pdp.api.value.Bag;
/**
* Immutable implementation of {@link IndividualPdpDecisionRequest} to be used as input to {@link BasePdpEngine}
*/
public final class ImmutablePdpDecisionRequest implements IndividualPdpDecisionRequest
{
private final Map<AttributeGUID, Bag<?>> attributes;
private final Map<String, XdmNode> extraContentsByCategory;
private final boolean isApplicablePolicyListReturned;
/**
* Create new instance
*
* @param namedAttributes
* named Attributes (no extra Content element)
* @param extraContentNodesByCategory
* extra XML Content elements by attribute Category
* @param includedInResult
* attributes to be include in the final Result
* @param returnApplicablePolicies
* return list of applicable policy identifiers; equivalent of XACML Request's ReturnPolicyIdList flag
*/
ImmutablePdpDecisionRequest(final Map<AttributeGUID, Bag<?>> namedAttributes, final Map<String, XdmNode> extraContentNodesByCategory, final boolean returnApplicablePolicies)
{
// these maps/lists may be updated later by put(...) method defined in this class
attributes = namedAttributes == null ? null : HashCollections.newImmutableMap(namedAttributes);
extraContentsByCategory = extraContentNodesByCategory == null ? null : HashCollections.newImmutableMap(extraContentNodesByCategory);
this.isApplicablePolicyListReturned = returnApplicablePolicies;
}
/*
* (non-Javadoc)
*
* @see org.ow2.authzforce.core.IndividualDecisionRequest#getNamedAttributes()
*/
@Override
public Map<AttributeGUID, Bag<?>> getNamedAttributes()
{
return attributes;
}
/*
* (non-Javadoc)
*
* @see org.ow2.authzforce.core.IndividualDecisionRequest#getExtraContentsByCategory()
*/
@Override
public Map<String, XdmNode> getExtraContentsByCategory()
{
return this.extraContentsByCategory;
}
/**
* @return the returnApplicablePolicyIdList
*/
@Override
public boolean isApplicablePolicyIdListReturned()
{
return isApplicablePolicyListReturned;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "[namedAttributes=" + attributes + ", extraContentsByCategory=" + extraContentsByCategory + ", returnApplicablePolicyIdList=" + isApplicablePolicyListReturned + "]";
}
}
......@@ -21,27 +21,35 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import net.sf.saxon.s9api.XdmNode;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.AttributeFQN;
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.PdpDecisionRequest;
import org.ow2.authzforce.core.pdp.api.StatusHelper;
import org.ow2.authzforce.core.pdp.api.UpdatableCollections;
import org.ow2.authzforce.core.pdp.api.UpdatableMap;
import org.ow2.authzforce.core.pdp.api.UpdatableSet;
import org.ow2.authzforce.core.pdp.api.expression.AttributeSelectorExpression;
import org.ow2.authzforce.core.pdp.api.value.AttributeBag;
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.Datatype;
import org.ow2.authzforce.core.pdp.api.value.StandardDatatypes;
import org.ow2.authzforce.core.pdp.api.value.Value;
import org.ow2.authzforce.core.pdp.api.value.XPathValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.MutableClassToInstanceMap;
/**
* 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).
......@@ -55,11 +63,7 @@ public final class IndividualDecisionRequestContext implements EvaluationContext
*/
private static final Logger LOGGER = LoggerFactory.getLogger(IndividualDecisionRequestContext.class);
private final Map<AttributeGUID, Bag<?>> namedAttributes;
private final Map<String, Value> varValsById = HashCollections.newMutableMap();
private final Map<String, Object> mutableProperties = HashCollections.newMutableMap();
private final Map<AttributeFQN, AttributeBag<?>> namedAttributes;
/*
* 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
......@@ -73,46 +77,39 @@ public final class IndividualDecisionRequestContext implements EvaluationContext
*/
private final UpdatableMap<AttributeSelectorId, Bag<?>> attributeSelectorResults;
// not null
private final UpdatableSet<AttributeGUID> usedNamedAttributeIdSet;
private final Map<String, Value> varValsById = HashCollections.newMutableMap();
// not null
private final UpdatableSet<AttributeSelectorId> usedAttributeSelectorIdSet;
private final Map<String, Object> mutableProperties = HashCollections.newMutableMap();
private final boolean returnApplicablePolicyIdList;
private final ClassToInstanceMap<Listener> listeners = MutableClassToInstanceMap.create();
/**
* Constructs a new <code>IndividualDecisionRequestContext</code> based on the given request attributes and extra contents with support for XPath evaluation against Content element in Attributes
*
* @param namedAttributeMap
* updatable named attribute map (attribute key and value pairs) from the original Request; null iff none. An attribute key is a global ID based on attribute category,issuer,id. An
* attribute value is a bag of primitive values.
* @param extraContentsByAttributeCategory
* @param extraContentsByCategory
* extra contents by attribute category (equivalent to XACML Attributes/Content elements); null iff no Content in the attribute category.
* @param returnApplicablePolicyIdList
* true iff list of IDs of policies matched during evaluation must be returned
* @param returnUsedAttributes
* true iff the list of attributes used during evaluation may be requested by
*/
public IndividualDecisionRequestContext(final Map<AttributeGUID, Bag<?>> namedAttributeMap, final Map<String, XdmNode> extraContentsByAttributeCategory,
final boolean returnApplicablePolicyIdList, final boolean returnUsedAttributes)
public IndividualDecisionRequestContext(final Map<AttributeFQN, AttributeBag<?>> namedAttributeMap, final Map<String, XdmNode> extraContentsByCategory, final boolean returnApplicablePolicyIdList)
{
this.namedAttributes = namedAttributeMap == null ? HashCollections.<AttributeGUID, Bag<?>> newUpdatableMap() : namedAttributeMap;
this.namedAttributes = namedAttributeMap == null ? HashCollections.<AttributeFQN, AttributeBag<?>> newUpdatableMap() : HashCollections
.<AttributeFQN, AttributeBag<?>> newUpdatableMap(namedAttributeMap);
this.returnApplicablePolicyIdList = returnApplicablePolicyIdList;
this.usedNamedAttributeIdSet = returnUsedAttributes ? UpdatableCollections.<AttributeGUID> newUpdatableSet() : UpdatableCollections.<AttributeGUID> emptySet();
if (extraContentsByAttributeCategory == null)
if (extraContentsByCategory == null)
{
this.extraContentsByAttributeCategory = Collections.emptyMap();
this.attributeSelectorResults = UpdatableCollections.emptyMap();
// not used since there is no <Content>
// (extraContentsByAttributeCategory == null)
this.usedAttributeSelectorIdSet = UpdatableCollections.emptySet();
}
else
{
this.extraContentsByAttributeCategory = extraContentsByAttributeCategory;
this.extraContentsByAttributeCategory = extraContentsByCategory;
this.attributeSelectorResults = UpdatableCollections.newUpdatableMap();
this.usedAttributeSelectorIdSet = returnUsedAttributes ? UpdatableCollections.<AttributeSelectorId> newUpdatableSet() : UpdatableCollections.<AttributeSelectorId> emptySet();
}
}
......@@ -121,46 +118,43 @@ public final class IndividualDecisionRequestContext implements EvaluationContext
*
* @param individualDecisionReq
* individual decision request
* @param returnUsedAttributes
* true iff the list of attributes used during evaluation may be requested by
*/
public IndividualDecisionRequestContext(final IndividualDecisionRequest individualDecisionReq, final boolean returnUsedAttributes)
public IndividualDecisionRequestContext(final PdpDecisionRequest individualDecisionReq)
{
this(individualDecisionReq.getNamedAttributes(), individualDecisionReq.getExtraContentsByCategory(), individualDecisionReq.isApplicablePolicyIdListReturned(), returnUsedAttributes);
this(individualDecisionReq.getNamedAttributes(), individualDecisionReq.getExtraContentsByCategory(), individualDecisionReq.isApplicablePolicyIdListReturned());
}
/** {@inheritDoc} */
@Override
public <AV extends AttributeValue> Bag<AV> getAttributeDesignatorResult(final AttributeGUID attributeGUID, final Datatype<AV> attributeDatatype) throws IndeterminateEvaluationException
public <AV extends AttributeValue> AttributeBag<AV> getNamedAttributeValue(final AttributeFQN attributeFQN, final BagDatatype<AV> attributeBagDatatype) throws IndeterminateEvaluationException