Commit 4ba471ea authored by cdanger's avatar cdanger

- Changed parent version: 4.1.1 -> 5.0.0

- Changed core-pdp-api: 8.2.0 -> 9.0.0
- Renamed PDPImpl to BasePdpEngine implements new PDPEngine API
- Removed/Merged PdpConfigurationParser into BasePdpEngine
- Added unit test of CXF authorization interceptor using AuthForce PDP
(BasePdpEngine), adapted from
https://github.com/coheigea/testcases/tree/master/apache/cxf/cxf-sts-xacml
parent a09f3ea7
......@@ -14,3 +14,4 @@
/.pmdruleset.xml
/.README.md.html
/.CHANGELOG.md.html
/target/
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-parent</artifactId>
<version>4.1.1</version>
<version>5.0.0</version>
</parent>
<artifactId>authzforce-ce-core</artifactId>
<version>6.1.1-SNAPSHOT</version>
......@@ -42,7 +42,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-core-pdp-api</artifactId>
<version>8.2.0</version>
<version>9.0.0</version>
</dependency>
<!-- /Authzforce dependencies -->
......@@ -57,6 +57,30 @@
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf.services.sts</groupId>
<artifactId>cxf-services-sts-core</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-testutils</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>
<!-- /Test dependencies -->
</dependencies>
......@@ -87,6 +111,7 @@
<excludeRoots>
<excludeRoot>target/generated-sources/xjc</excludeRoot>
<excludeRoot>target/generated-test-sources/xjc</excludeRoot>
<excludeRoot>target/generated-test-sources/cxf</excludeRoot>
</excludeRoots>
</configuration>
<executions>
......@@ -103,6 +128,7 @@
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.ow2.authzforce.*</onlyAnalyze>
<excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
</configuration>
<executions>
......@@ -121,9 +147,9 @@
<configuration>
<header>license/thales-gpl.header.txt</header>
<includes>
<include>src/main/java/org/ow2/authzforce/core/**</include>
<include>src/main/java/org/ow2/authzforce/**</include>
<!-- Include test files also -->
<include>src/test/java/**</include>
<include>src/test/java/org/ow2/authzforce/**</include>
</includes>
</configuration>
<executions>
......@@ -176,7 +202,6 @@
<episode>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-pdp-ext-model</artifactId>
<version>3.4.0</version>
</episode>
</episodes>
<catalog>src/main/jaxb/catalog.xml</catalog>
......@@ -217,6 +242,31 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>
${basedir}/target/generated-test-sources/cxf
</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>
${basedir}/src/test/resources/org/apache/coheigea/cxf/sts/xacml/common/DoubleItLogical.wsdl
</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Test configuration -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
......
/**
*
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistribution in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED
* WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use in the design, construction, operation or maintenance of any nuclear facility.
*/
package com.sun.xacml;
/**
* Exception that gets thrown if an unknown identifier was used, such as the identifier used in any of the standard
* factories.
*
* @since 1.0
* @author Seth Proctor
* @version $Id: $
*/
public final class UnknownIdentifierException extends Exception
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Creates an <code>UnknownIdentifierException</code> with no data
*/
public UnknownIdentifierException()
{
}
/**
* Creates an <code>UnknownIdentifierException</code> with a message
*
* @param message
* the message
*/
public UnknownIdentifierException(String message)
{
super(message);
}
}
/**
* Copyright (C) 2012-2017 Thales Services SAS.
*
* This file is part of AuthZForce CE.
*
* AuthZForce CE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AuthZForce CE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AuthZForce CE. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
*/
package org.ow2.authzforce.core.pdp.impl;
import java.util.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 + "]";
}
}
......@@ -18,6 +18,7 @@
*/
package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
......@@ -25,10 +26,13 @@ import java.util.Map;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Result;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.DecisionResultFilter;
import org.ow2.authzforce.core.pdp.api.DecisionResultFilter.FilteringResultCollector;
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.PdpDecisionResult;
import org.ow2.authzforce.core.pdp.api.StatusHelper;
import org.ow2.authzforce.core.pdp.api.value.Bag;
......@@ -165,9 +169,60 @@ public abstract class IndividualDecisionRequestEvaluator
};
private static final class DefaultResultCollector implements FilteringResultCollector
{
private final List<Result> results;
private DefaultResultCollector(final int numberOfFilteredResults)
{
results = new ArrayList<>(numberOfFilteredResults);
}
@Override
public List<Result> addResult(final IndividualDecisionRequest request, final PdpDecisionResult result)
{
results.add(result.toXACMLResult(request.getReturnedAttributes()));
return null;
}
@Override
public List<Result> getFilteredResults()
{
return results;
}
}
private static final DecisionResultFilter DEFAULT_RESULT_FILTER = new DecisionResultFilter()
{
private static final String ID = "urn:ow2:authzforce:feature:pdp:result-filter:default";
@Override
public String getId()
{
return ID;
}
@Override
public boolean supportsMultipleDecisionCombining()
{
return false;
}
@Override
public FilteringResultCollector newResultCollector(final int numberOfInputResults)
{
return new DefaultResultCollector(numberOfInputResults);
}
};
private final RootPolicyEvaluator rootPolicyEvaluator;
private final RequestAndPdpIssuedNamedAttributesMerger reqAndPdpIssuedAttributesMerger;
private final DecisionResultFilter decisionResultFilter;
/**
* Creates an evaluator
*
......@@ -189,10 +244,13 @@ public abstract class IndividualDecisionRequestEvaluator
* attributes are not present in the decision request, then their values MUST be supplied by the context handler " but it does NOT say "If AND ONLY IF values..." So this option could
* still be considered XACML compliant in a strict sense.</li>
* </ul>
* @param resultFilter
* Decision Result filter
* @throws IllegalArgumentException
* if {@code stdEnvAttributeSource} is null or not supported
*/
protected IndividualDecisionRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource) throws IllegalArgumentException
protected IndividualDecisionRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource, final DecisionResultFilter resultFilter)
throws IllegalArgumentException
{
assert rootPolicyEvaluator != null && stdEnvAttributeSource != null;
this.rootPolicyEvaluator = rootPolicyEvaluator;
......@@ -214,11 +272,26 @@ public abstract class IndividualDecisionRequestEvaluator
default:
throw new IllegalArgumentException("Unsupported standardEnvAttributeSource: " + stdEnvAttributeSource + ". Expected: " + Arrays.toString(StandardEnvironmentAttributeSource.values()));
}
this.decisionResultFilter = resultFilter == null ? DEFAULT_RESULT_FILTER : resultFilter;
}
final boolean supportsMultipleDecisionCombining()
{
return this.decisionResultFilter.supportsMultipleDecisionCombining();
}
protected final FilteringResultCollector beginMultipleDecisions(final int numOfRequests)
{
/*
* There will be at most as many results as requests, so we prepare to filter at most numOfRequests results
*/
return decisionResultFilter.newResultCollector(numOfRequests);
}
/**
* <p>
* evaluate
* Evaluate an Individual Decision Request, with option to return attributes used by the evaluation, e.g. to improve caching mechanisms
* </p>
*
* @param request
......@@ -229,7 +302,7 @@ public abstract class IndividualDecisionRequestEvaluator
* true iff the list of attributes used for evaluation must be included in the result
* @return the evaluation result.
*/
protected final PdpDecisionResult evaluate(final IndividualDecisionRequest request, final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes, final boolean returnUsedAttributes)
protected final PdpDecisionResult evaluate(final PdpDecisionRequest request, final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes, final boolean returnUsedAttributes)
{
assert request != null;
LOGGER.debug("Evaluating Individual Decision Request: {}", request);
......@@ -243,15 +316,45 @@ public abstract class IndividualDecisionRequestEvaluator
/**
* <p>
* evaluate
* Evaluate an Individual Decision Request.
* </p>
*
* @param individualDecisionRequest
* an individual decision request
* @return the evaluation result pair
*/
protected abstract PdpDecisionResult evaluate(PdpDecisionRequest individualDecisionRequest, final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes);
/**
* <p>
* Evaluate multiple Individual Decision Requests with same PDP-issued attribute values (e.g. current date/time) in order to return decision results in internal model (more efficient than JAXB
* model derived from XACML schema as in {@link #evaluateToJAXB(List, Map)}).
* </p>
*
* @param individualDecisionRequests
* a {@link java.util.List} of individual decision requests.
* @param pdpIssuedAttributes
* a {@link java.util.Map} of PDP-issued attributes including at least the standard environment attributes: current-time, current-date, current-dateTime.
* @return individual decision request-result pairs, where the list of the requests is the same as {@code individualDecisionRequests}.
* @throws IndeterminateEvaluationException
* if an error occurred preventing any request evaluation
*/
protected abstract <INDIVIDUAL_DECISION_REQ_T extends PdpDecisionRequest> Map<INDIVIDUAL_DECISION_REQ_T, ? extends PdpDecisionResult> evaluate(
List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes) throws IndeterminateEvaluationException;
/**
* <p>
* Evaluate multiple Individual Decision Requests with same PDP-issued attribute values (e.g. current date/time) in order to return JAXB {@link Result}s. Use only if you need to produce a final
* XACML/JAXB Result or Response for serialization (esp. to interoperate with external systems, where external means outside the current runtime JVM), else use
* {@link #evaluate(PdpDecisionRequest, Map)} which is more optimal.
* </p>
*
* @param individualDecisionRequests
* a {@link java.util.List} of individual decision requests.
* @param pdpIssuedAttributes
* a {@link java.util.Map} of PDP-issued attributes including at least the standard environment attributes: current-time, current-date, current-dateTime.
* @return a {@link java.util.List} of evaluation results (one per individual decision request).
* @return a {@link java.util.List} of XACML {@link Result}s (one per individual decision request), ready to be included in a final XACML Response.
*/
protected abstract <INDIVIDUAL_DECISION_REQ_T extends IndividualDecisionRequest> List<Result> evaluate(List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests,
final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes);
protected abstract List<Result> evaluateToJAXB(List<? extends IndividualDecisionRequest> individualDecisionRequests, final Map<AttributeGUID, Bag<?>> pdpIssuedAttributes);
}
......@@ -24,10 +24,11 @@ import java.util.Map;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Request;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Response;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Result;
import org.ow2.authzforce.core.pdp.api.IndividualDecisionRequest;
import org.ow2.authzforce.core.pdp.api.PDP;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.PDPEngine;
import org.ow2.authzforce.core.pdp.api.PdpDecisionRequestBuilder;
import org.ow2.authzforce.core.pdp.api.PdpDecisionResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SystemPropertyUtils;
......@@ -42,11 +43,11 @@ import org.springframework.util.SystemPropertyUtils;
*
* @version $Id: $
*/
public final class PdpBean implements PDP
public final class PdpBean implements PDPEngine<ImmutablePdpDecisionRequest>
{
private final static Logger LOGGER = LoggerFactory.getLogger(PdpBean.class);
private PDP pdp;
private PDPEngine<ImmutablePdpDecisionRequest> pdp;
private String confLocation = null;
......@@ -105,11 +106,12 @@ public final class PdpBean implements PDP
{
if (!initialized && catalogLocation != null && extSchemaLocation != null && confLocation != null)
{
LOGGER.info("Loading PDP configuration from file {} with extension schema location '{}' and XML catalog location '{}'", new Object[] { confLocation, extSchemaLocation, catalogLocation });
LOGGER.info("Loading PDP configuration from file {} with extension schema location '{}' and XML catalog location '{}'", confLocation, extSchemaLocation, catalogLocation);
try
{
pdp = PdpConfigurationParser.getPDP(confLocation, catalogLocation, extSchemaLocation);
} catch (IOException | IllegalArgumentException e)
pdp = BasePdpEngine.getInstance(confLocation, catalogLocation, extSchemaLocation);
}
catch (IOException | IllegalArgumentException e)
{
throw new RuntimeException("Error parsing PDP configuration from location: " + confLocation, e);
}
......@@ -120,6 +122,12 @@ public final class PdpBean implements PDP
return initialized;
}
@Override
public PdpDecisionRequestBuilder<ImmutablePdpDecisionRequest> newRequestBuilder(final int expectedNumOfAttributeCategories, final int expectedTotalNumOfAttributes)
{
return pdp.newRequestBuilder(expectedNumOfAttributeCategories, expectedTotalNumOfAttributes);
}
/** {@inheritDoc} */
@Override
public Response evaluate(final Request request)
......@@ -135,13 +143,16 @@ public final class PdpBean implements PDP
if (confLocation == null)
{
cause = "Missing parameter: configuration file";
} else if (extSchemaLocation == null)
}
else if (extSchemaLocation == null)
{
cause = "Missing parameter: extension schema file";
} else if (catalogLocation == null)
}
else if (catalogLocation == null)
{
cause = "Missing parameter: XML catalog file";
} else
}
else
{
cause = "Check previous errors.";
}
......@@ -152,10 +163,17 @@ public final class PdpBean implements PDP
/** {@inheritDoc} */
@Override
public <INDIVIDUAL_DECISION_REQUEST_T extends IndividualDecisionRequest> List<Result> evaluate(final List<INDIVIDUAL_DECISION_REQUEST_T> individualDecisionRequests)
public PdpDecisionResult evaluate(final ImmutablePdpDecisionRequest individualDecisionRequest)
{
checkInit();
return pdp.evaluate(individualDecisionRequest);
}
@Override
public Map<ImmutablePdpDecisionRequest, ? extends PdpDecisionResult> evaluate(final List<ImmutablePdpDecisionRequest> requests) throws IndeterminateEvaluationException
{
checkInit();
return pdp.evaluate(individualDecisionRequests);
return pdp.evaluate(requests);
}
/** {@inheritDoc} */
......
......@@ -23,7 +23,7 @@ import java.util.Map;
import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.xacml.identifiers.XACMLAttributeId;
import org.ow2.authzforce.xacml.identifiers.XACMLCategory;
import org.ow2.authzforce.xacml.identifiers.XACMLAttributeCategory;
import com.google.common.collect.Maps;
......@@ -38,17 +38,17 @@ public enum StandardEnvironmentAttribute
/**
* urn:oasis:names:tc:xacml:1.0:environment:current-time
*/
CURRENT_TIME(new AttributeGUID(XACMLCategory.XACML_3_0_ENVIRONMENT_CATEGORY_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_TIME.value())),
CURRENT_TIME(new AttributeGUID(XACMLAttributeCategory.XACML_3_0_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_TIME.value())),
/**
* urn:oasis:names:tc:xacml:1.0:environment:current-date
*/
CURRENT_DATE(new AttributeGUID(XACMLCategory.XACML_3_0_ENVIRONMENT_CATEGORY_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_DATE.value())),
CURRENT_DATE(new AttributeGUID(XACMLAttributeCategory.XACML_3_0_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_DATE.value())),
/**
* urn:oasis:names:tc:xacml:1.0:environment:current-dateTime
*/
CURRENT_DATETIME(new AttributeGUID(XACMLCategory.XACML_3_0_ENVIRONMENT_CATEGORY_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_DATETIME.value()));
CURRENT_DATETIME(new AttributeGUID(XACMLAttributeCategory.XACML_3_0_ENVIRONMENT.value(), null, XACMLAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_DATETIME.value()));