From fe3a8ec467beae89bca9d10b8b5b39f98c81ca01 Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Mon, 4 Nov 2019 16:18:08 -0500 Subject: Implement closest match algorithm Needed to add more obligations, which make it easier to scan through obligations and be able to pull information about the policy. Adding weight as an obligation for Optimization policies in order to implement "closest match" algorithm. Moved Obligation to a support class. Added JUnit code coverage on the translator classes. Split some methods up to reduce complexity via sonar. Issue-ID: POLICY-2066 Change-Id: Ibb13d2dc0a63ab2a6d585b0697a0c1d129fa8f7b Signed-off-by: Pamela Dragosh --- .../xacml/application/common/OnapObligation.java | 259 +++++++++++++++++++++ .../xacml/application/common/ToscaDictionary.java | 37 ++- .../application/common/std/StdBaseTranslator.java | 94 ++------ .../std/StdCombinedPolicyResultsTranslator.java | 83 ++++++- .../common/std/StdMatchableTranslator.java | 158 ++++++++++++- .../application/common/OnapObligationTest.java | 144 ++++++++++++ .../xacml/application/common/TestUtilsCommon.java | 126 ++++++++++ .../application/common/ToscaDictionaryTest.java | 5 - .../common/std/StdBaseTranslatorTest.java | 198 +++++++++++++++- .../StdCombinedPolicyResultsTranslatorTest.java | 155 ++++++++++++ .../common/std/StdMatchablePolicyRequestTest.java | 35 --- .../common/std/StdMatchableTranslatorTest.java | 84 ++++++- .../common/src/test/resources/test.policy.bad.json | 17 ++ .../common/src/test/resources/test.policy.json | 21 ++ 14 files changed, 1272 insertions(+), 144 deletions(-) create mode 100644 applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java create mode 100644 applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java create mode 100644 applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java create mode 100644 applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java create mode 100644 applications/common/src/test/resources/test.policy.bad.json create mode 100644 applications/common/src/test/resources/test.policy.json (limited to 'applications/common/src') diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java new file mode 100644 index 00000000..da2e7f10 --- /dev/null +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java @@ -0,0 +1,259 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common; + +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Obligation; +import com.google.gson.Gson; +import java.util.Map; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.ToString; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType; + +@Getter +@ToString +public class OnapObligation { + + @Getter(AccessLevel.NONE) + private static final ObjectFactory factory = new ObjectFactory(); + + @Getter(AccessLevel.NONE) + private static final Gson gson = new Gson(); + + private String policyId; + private String policyType; + private String policyContent; + private Integer weight; + + /** + * Constructor from an obligation. + * + * @param obligation Obligation object + */ + public OnapObligation(Obligation obligation) { + // + // Scan through the obligations for them + // + for (AttributeAssignment assignment : obligation.getAttributeAssignments()) { + scanAttribute(assignment); + } + } + + /** + * Constructor for just the policy details. + * + * @param policyId String + * @param policyContent String + */ + public OnapObligation(String policyId, String policyContent) { + this.policyId = policyId; + this.policyContent = policyContent; + } + + + /** + * Constructor for policy details, type and weight. + * + * @param policyId String + * @param policyContent String + * @param policyType String + * @param weight int + */ + public OnapObligation(String policyId, String policyContent, String policyType, Integer weight) { + this.policyId = policyId; + this.policyContent = policyContent; + this.policyType = policyType; + this.weight = weight; + } + + /** + * getPolicyContentAsMap returns the policy as a map for convience. + * + * @return {@code Map} + */ + @SuppressWarnings("unchecked") + public Map getPolicyContentAsMap() { + if (this.policyContent == null) { + return null; + } + return gson.fromJson(this.policyContent, Map.class); + } + + /** + * Generates default obligation using default Permit and Obligation Id. + * + * @return ObligationExpressionType object + */ + public ObligationExpressionType generateObligation() { + return this.generateObligation(EffectType.PERMIT, ToscaDictionary.ID_OBLIGATION_REST_BODY); + } + + /** + * generateObligation - generates an obligation object with the attributes that exist. Note: + * any null values will result in NO attribute assignment for that attribute. + * + * @param effectType EffectType object + * @param obligationId Id for the obligation + * @return ObligationExpressionType object + */ + public ObligationExpressionType generateObligation(EffectType effectType, Identifier obligationId) { + // + // Create an ObligationExpression + // + ObligationExpressionType obligation = new ObligationExpressionType(); + obligation.setFulfillOn(effectType); + obligation.setObligationId(obligationId.stringValue()); + // + // Update the obligation + // + updateObligation(obligation); + // + // Convenience return + // + return obligation; + } + + /** + * Updates an existing Obligation object with the attributes that exist. Note: any null values + * will result in NO attribute assignment for that attribute. + * + * @param obligation ObligationExpressionType object + * @return ObligationExpressionType object + */ + public ObligationExpressionType updateObligation(ObligationExpressionType obligation) { + // + // Add policy-id + // + addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_ID, + ToscaDictionary.ID_OBLIGATION_POLICY_ID_DATATYPE, + ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY, + policyId); + // + // Add policy contents + // + addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT, + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_DATATYPE, + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY, + policyContent); + // + // Add the weight + // + addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT, + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_DATATYPE, + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY, + weight); + // + // Add the policy type + // + addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_TYPE, + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_DATATYPE, + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY, + policyType); + // + // Return as a convenience + // + return obligation; + } + + /** + * scanAttribute - scans the assignment for a supported obligation assignment. Applications + * can override this class and provide their own custom attribute assignments if desired. + * + * @param assignment AttributeAssignment object + * @return true if found an ONAP supported attribute + */ + protected boolean scanAttribute(AttributeAssignment assignment) { + // + // Check for our supported attributes. Note: Cannot use a switch + // as Identifier isn't a constant. + // + if (ToscaDictionary.ID_OBLIGATION_POLICY_ID.equals(assignment.getAttributeId())) { + policyId = assignment.getAttributeValue().getValue().toString(); + return true; + } else if (ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.equals(assignment.getAttributeId())) { + policyType = assignment.getAttributeValue().getValue().toString(); + return true; + } else if (ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.equals(assignment.getAttributeId())) { + policyContent = assignment.getAttributeValue().getValue().toString(); + return true; + } else if (ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.equals(assignment.getAttributeId())) { + weight = Integer.decode(assignment.getAttributeValue().getValue().toString()); + return true; + } + // + // By returning true, we indicate this isn't an attribute + // supported in the this class. Targeted for applications + // that derive from this class in order to extend it. + // + return false; + } + + /** + * Creates the necessary objects to insert into the obligation, if the value object is not null. + * + * @param obligation Incoming Obligation + * @param id Attribute Id + * @param datatype Attribute's Data type + * @param category Attributes Category + * @param theValue Attribute value + * @return obligation Incoming obligation + */ + protected ObligationExpressionType addOptionalAttributeToObligation(ObligationExpressionType obligation, + Identifier id, Identifier datatype, Identifier category, Object theValue) { + // + // Simple check for null + // + if (theValue == null) { + return obligation; + } + // + // Create an AttributeValue for it + // + AttributeValueType value = new AttributeValueType(); + value.setDataType(datatype.stringValue()); + value.getContent().add(theValue.toString()); + // + // Create our AttributeAssignmentExpression where we will + // store the contents of the policy id. + // + AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType(); + expressionType.setAttributeId(id.stringValue()); + expressionType.setCategory(category.stringValue()); + expressionType.setExpression(factory.createAttributeValue(value)); + // + // Add it to the obligation + // + obligation.getAttributeAssignmentExpression().add(expressionType); + // + // Return as convenience + // + return obligation; + } + +} diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java index 500be2e6..1a899971 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java @@ -112,20 +112,41 @@ public final class ToscaDictionary { public static final Identifier ID_OBLIGATION_REST_BODY = new IdentifierImpl(ID_URN_ONAP, "rest:body"); - public static final Identifier ID_OBLIGATION_POLICY_MONITORING = - new IdentifierImpl(ID_URN_ONAP, ":obligation:monitoring"); + public static final Identifier ID_OBLIGATION_POLICY_CONTENT = + new IdentifierImpl(ID_URN_ONAP, ":obligation:policycontent"); - public static final Identifier ID_OBLIGATION_POLICY_MONITORING_CONTENTS = - new IdentifierImpl(ID_URN_ONAP, ":obligation:monitoring:contents"); + public static final Identifier ID_OBLIGATION_POLICY_CONTENT_CATEGORY = + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE; + + public static final Identifier ID_OBLIGATION_POLICY_CONTENT_DATATYPE = + XACML3.ID_DATATYPE_STRING; - public static final Identifier ID_OBLIGATION_POLICY_MONITORING_CATEGORY = + public static final Identifier ID_OBLIGATION_POLICY_ID = + new IdentifierImpl(ID_URN_ONAP, ":obligation:policyid"); + + public static final Identifier ID_OBLIGATION_POLICY_ID_CATEGORY = XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE; - public static final Identifier ID_OBLIGATION_POLICY_MONITORING_DATATYPE = + public static final Identifier ID_OBLIGATION_POLICY_ID_DATATYPE = XACML3.ID_DATATYPE_STRING; - public static final Identifier ID_OBLIGATION_MONITORING_ISSUER = - new IdentifierImpl(ID_URN_ONAP, "issuer:monitoring"); + public static final Identifier ID_OBLIGATION_POLICY_WEIGHT = + new IdentifierImpl(ID_URN_ONAP, ":obligation:weight"); + + public static final Identifier ID_OBLIGATION_POLICY_WEIGHT_CATEGORY = + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE; + + public static final Identifier ID_OBLIGATION_POLICY_WEIGHT_DATATYPE = + XACML3.ID_DATATYPE_INTEGER; + + public static final Identifier ID_OBLIGATION_POLICY_TYPE = + new IdentifierImpl(ID_URN_ONAP, ":obligation:policytype"); + + public static final Identifier ID_OBLIGATION_POLICY_TYPE_CATEGORY = + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE; + + public static final Identifier ID_OBLIGATION_POLICY_TYPE_DATATYPE = + XACML3.ID_DATATYPE_STRING; diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslator.java index d2d383b9..508bc245 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslator.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslator.java @@ -22,24 +22,20 @@ package org.onap.policy.pdp.xacml.application.common.std; -import com.att.research.xacml.api.AttributeAssignment; import com.att.research.xacml.api.Decision; import com.att.research.xacml.api.Obligation; import com.att.research.xacml.api.Request; import com.att.research.xacml.api.Response; import com.att.research.xacml.api.Result; import com.att.research.xacml.api.XACML3; -import com.google.gson.Gson; import java.util.Collection; import java.util.HashMap; import java.util.Map; import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory; import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType; @@ -50,6 +46,7 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.OnapObligation; import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; @@ -58,16 +55,16 @@ import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class StdBaseTranslator implements ToscaPolicyTranslator { +public abstract class StdBaseTranslator implements ToscaPolicyTranslator { private static final Logger LOGGER = LoggerFactory.getLogger(StdBaseTranslator.class); - private static Gson gson = new Gson(); + private static final ObjectFactory factory = new ObjectFactory(); public static final String POLICY_ID = "policy-id"; public static final String POLICY_VERSION = "policy-version"; @Override public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { - throw new ToscaPolicyConversionException("Please override converPolicy"); + throw new ToscaPolicyConversionException("Please override convertPolicy"); } @Override @@ -95,8 +92,7 @@ public class StdBaseTranslator implements ToscaPolicyTranslator { // Go through obligations // scanObligations(xacmlResult.getObligations(), decisionResponse); - } else if (xacmlResult.getDecision() == Decision.DENY - || xacmlResult.getDecision() == Decision.INDETERMINATE) { + } else { // // TODO we have to return an ErrorResponse object instead // @@ -109,55 +105,13 @@ public class StdBaseTranslator implements ToscaPolicyTranslator { /** * scanObligations - scans the list of obligations and make appropriate method calls to process - * obligations. + * obligations. This method must be overridden and be implemented for the specific application as + * obligations may have different expected attributes per application. * * @param obligations Collection of obligation objects * @param decisionResponse DecisionResponse object used to store any results from obligations. */ - protected void scanObligations(Collection obligations, DecisionResponse decisionResponse) { - for (Obligation obligation : obligations) { - LOGGER.info("Obligation: {}", obligation); - for (AttributeAssignment assignment : obligation.getAttributeAssignments()) { - LOGGER.info("Attribute Assignment: {}", assignment); - processObligationAttribute(assignment, decisionResponse); - } - } - } - - /** - * processObligationAttribute - processes an individual obligation attribute assignment object. - * - * @param assignment AttributeAssignment object - * @param decisionResponse DecisionResponse object used to store any results from attribute assignment. - */ - @SuppressWarnings("unchecked") - protected void processObligationAttribute(AttributeAssignment assignment, DecisionResponse decisionResponse) { - // - // We care about the content attribute - // - if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS - .equals(assignment.getAttributeId())) { - // - // The contents are in Json form - // - Object stringContents = assignment.getAttributeValue().getValue(); - LOGGER.info("DCAE contents: {}{}", XacmlPolicyUtils.LINE_SEPARATOR, stringContents); - // - // Let's parse it into a map using Gson - // - Map result; - result = gson.fromJson(stringContents.toString(), Map.class); - // - // Find the metadata section - // - Map metadata = (Map) result.get("metadata"); - if (metadata != null) { - decisionResponse.getPolicies().put(metadata.get(POLICY_ID).toString(), result); - } else { - LOGGER.error("Missing metadata section in policy contained in obligation."); - } - } - } + protected abstract void scanObligations(Collection obligations, DecisionResponse decisionResponse); /** * From the TOSCA metadata section, pull in values that are needed into the XACML policy. @@ -196,36 +150,27 @@ public class StdBaseTranslator implements ToscaPolicyTranslator { * But this is fine for now. * * @param RuleType, PolicyType, PolicySetType object + * @Param policyId The policy-id * @param ruleOrPolicy Incoming RuleType, PolicyType, PolicySetType object * @param jsonPolicy JSON String representation of policy. + * @param weight Weighting for the policy (optional) * @return Return the Incoming RuleType, PolicyType, PolicySetType object for convenience. */ - protected T addObligation(T ruleOrPolicy, String jsonPolicy) { + protected T addObligation(T ruleOrPolicy, String policyId, String jsonPolicy, Integer weight, + String policyType) { // // Creating obligation for returning policy // - LOGGER.info("Obligation Policy {}{}", XacmlPolicyUtils.LINE_SEPARATOR, jsonPolicy); - // - // Create an AttributeValue for it - // - AttributeValueType value = new AttributeValueType(); - value.setDataType(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_DATATYPE.stringValue()); - value.getContent().add(jsonPolicy); + LOGGER.info("Obligation Policy id: {} type: {} weight: {} policy:{}{}", policyId, policyType, weight, + XacmlPolicyUtils.LINE_SEPARATOR, jsonPolicy); // - // Create our AttributeAssignmentExpression where we will - // store the contents of the policy in JSON format. + // Create our OnapObligation // - AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType(); - expressionType.setAttributeId(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS.stringValue()); - ObjectFactory factory = new ObjectFactory(); - expressionType.setExpression(factory.createAttributeValue(value)); + OnapObligation onapObligation = new OnapObligation(policyId, jsonPolicy, policyType, weight); // - // Create an ObligationExpression for it + // Generate the obligation // - ObligationExpressionType obligation = new ObligationExpressionType(); - obligation.setFulfillOn(EffectType.PERMIT); - obligation.setObligationId(ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue()); - obligation.getAttributeAssignmentExpression().add(expressionType); + ObligationExpressionType obligation = onapObligation.generateObligation(); // // Now we can add it into the rule/policy/policyset // @@ -237,6 +182,8 @@ public class StdBaseTranslator implements ToscaPolicyTranslator { ((PolicyType) ruleOrPolicy).setObligationExpressions(obligations); } else if (ruleOrPolicy instanceof PolicySetType) { ((PolicySetType) ruleOrPolicy).setObligationExpressions(obligations); + } else { + LOGGER.error("Unsupported class for adding obligation {}", ruleOrPolicy.getClass()); } // // Return as a convenience @@ -300,7 +247,6 @@ public class StdBaseTranslator implements ToscaPolicyTranslator { valueZero.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); valueZero.getContent().add("0"); // Yes really - represent as a string - ObjectFactory factory = new ObjectFactory(); applyBagSize.getExpression().add(factory.createAttributeDesignator(designator)); ApplyType applyGreaterThan = new ApplyType(); diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java index be0a507e..bcd594fb 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java @@ -23,9 +23,14 @@ package org.onap.policy.pdp.xacml.application.common.std; import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Obligation; import com.att.research.xacml.api.Request; import com.att.research.xacml.api.XACML3; import com.att.research.xacml.std.annotations.RequestParser; +import com.google.common.base.Strings; +import java.util.Collection; +import java.util.Map; import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; @@ -35,7 +40,9 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.OnapObligation; import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; @@ -52,11 +59,24 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator { @Override public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + // + // Sanity checks + // + if (toscaPolicy == null) { + throw new ToscaPolicyConversionException("Cannot convert a NULL policy"); + } + if (toscaPolicy.getMetadata() == null) { + throw new ToscaPolicyConversionException("Cannot convert a policy with missing metadata section"); + } + // + // Get the policy Id + // + String policyId = toscaPolicy.getMetadata().get(POLICY_ID); // // Set it as the policy ID // PolicyType newPolicyType = new PolicyType(); - newPolicyType.setPolicyId(toscaPolicy.getMetadata().get(POLICY_ID)); + newPolicyType.setPolicyId(policyId); // // Optional description // @@ -72,8 +92,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator { // // Generate the TargetType // - TargetType target = this.generateTargetType(toscaPolicy.getMetadata().get(POLICY_ID), - toscaPolicy.getType(), toscaPolicy.getVersion()); + TargetType target = this.generateTargetType(policyId, toscaPolicy.getType(), toscaPolicy.getVersion()); newPolicyType.setTarget(target); // // Now create the Permit Rule @@ -82,7 +101,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator { // RuleType rule = new RuleType(); rule.setDescription("Default is to PERMIT if the policy matches."); - rule.setRuleId(toscaPolicy.getMetadata().get(POLICY_ID) + ":rule"); + rule.setRuleId(policyId + ":rule"); rule.setEffect(EffectType.PERMIT); rule.setTarget(new TargetType()); // @@ -95,7 +114,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator { } catch (CoderException e) { throw new ToscaPolicyConversionException(e); } - addObligation(rule, jsonPolicy); + addObligation(rule, policyId, jsonPolicy, null, toscaPolicy.getType()); // // Add the rule to the policy // @@ -120,6 +139,60 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator { return null; } + /** + * scanObligations - scans the list of obligations and make appropriate method calls to process + * obligations. + * + * @param obligations Collection of obligation objects + * @param decisionResponse DecisionResponse object used to store any results from obligations. + */ + @Override + protected void scanObligations(Collection obligations, DecisionResponse decisionResponse) { + for (Obligation obligation : obligations) { + Identifier obligationId = obligation.getId(); + LOGGER.info("Obligation: {}", obligationId); + if (ToscaDictionary.ID_OBLIGATION_REST_BODY.equals(obligationId)) { + scanContentObligation(obligation, decisionResponse); + } + } + } + + /** + * scanContentObligation - scans the specific obligation for policy-id and policy-content. + * + * @param obligation Obligation incoming obligation object + * @param decisionResponse DecisionResponse object + */ + protected void scanContentObligation(Obligation obligation, DecisionResponse decisionResponse) { + // + // Create our OnapObligation which will scan for attributes + // + OnapObligation onapObligation = new OnapObligation(obligation); + // + // Get the attributes we care about + // + String policyId = onapObligation.getPolicyId(); + Map policyContent = onapObligation.getPolicyContentAsMap(); + // + // Sanity check that we got the attributes we care about. NOTE: This translator + // ensures that these are set when convertPolicy is called. + // + if (! Strings.isNullOrEmpty(policyId) && policyContent != null) { + decisionResponse.getPolicies().put(policyId, policyContent); + } else { + LOGGER.error("Missing obligation policyId {} or policyContent {}", policyId, + policyContent == null ? "null" : policyContent.size()); + } + } + + /** + * generateTargetType - Generates a TargetType object for the policy-id and policy-type. + * + * @param policyId String policy-id + * @param policyType String policy type + * @param policyTypeVersion String policy type version + * @return TargetType object + */ protected TargetType generateTargetType(String policyId, String policyType, String policyTypeVersion) { // // Create all the match's that are possible diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java index 66770e91..addb0df3 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java @@ -23,6 +23,7 @@ package org.onap.policy.pdp.xacml.application.common.std; import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Obligation; import com.att.research.xacml.api.Request; import com.att.research.xacml.api.XACML3; import com.att.research.xacml.std.IdentifierImpl; @@ -38,6 +39,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -48,17 +51,20 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType; +import org.apache.commons.lang3.tuple.Pair; import org.onap.policy.common.endpoints.parameters.RestServerParameters; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.StandardYamlCoder; import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; +import org.onap.policy.pdp.xacml.application.common.OnapObligation; import org.onap.policy.pdp.xacml.application.common.PolicyApiCaller; import org.onap.policy.pdp.xacml.application.common.PolicyApiException; import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; @@ -104,6 +110,127 @@ public class StdMatchableTranslator extends StdBaseTranslator { return null; } + /** + * scanObligations - scans the list of obligations and make appropriate method calls to process + * obligations. + * + * @param obligations Collection of obligation objects + * @param decisionResponse DecisionResponse object used to store any results from obligations. + */ + @Override + protected void scanObligations(Collection obligations, DecisionResponse decisionResponse) { + // + // Implementing a crude "closest match" on the results, which means we will strip out + // any policies that has the lower weight than any of the others. + // + // Most likely these are "default" policies with a weight of zero, but not always. + // + // It is possible to have multiple policies with an equal weight, that is desired. + // + // So we need to track each policy type separately and the weights for each policy. + // + // policy-type -> weight -> List({policy-id, policy-content}, {policy-id, policy-content}) + // + Map>>>> closestMatches = new LinkedHashMap<>(); + // + // Now scan the list of obligations + // + for (Obligation obligation : obligations) { + Identifier obligationId = obligation.getId(); + LOGGER.info("Obligation: {}", obligationId); + if (ToscaDictionary.ID_OBLIGATION_REST_BODY.equals(obligationId)) { + scanClosestMatchObligation(closestMatches, obligation); + } else { + LOGGER.warn("Unsupported Obligation Id {}", obligation.getId()); + } + } + // + // Now add all the policies to the DecisionResponse + // + closestMatches.forEach((thePolicyType, weightMap) -> + weightMap.forEach((weight, policies) -> + policies.forEach(policy -> { + LOGGER.info("Policy {}", policy); + decisionResponse.getPolicies().put(policy.getLeft(), policy.getRight()); + }) + ) + ); + } + + /** + * scanClosestMatchObligation - scans for the obligation specifically holding policy + * contents and their details. + * + * @param closestMatches Map holding the current set of highest weight policy types + * @param Obligation Obligation object + */ + protected void scanClosestMatchObligation( + Map>>>> closestMatches, Obligation obligation) { + // + // Create our OnapObligation object + // + OnapObligation onapObligation = new OnapObligation(obligation); + // + // All 4 *should* be there + // + if (onapObligation.getPolicyId() == null || onapObligation.getPolicyContent() == null + || onapObligation.getPolicyType() == null || onapObligation.getWeight() == null) { + LOGGER.error("Missing an expected attribute in obligation."); + return; + } + // + // Save the values + // + String policyId = onapObligation.getPolicyId(); + String policyType = onapObligation.getPolicyType(); + Map policyContent = onapObligation.getPolicyContentAsMap(); + int policyWeight = onapObligation.getWeight(); + // + // If the Policy Type exists, get the weight map. + // + Map>>> weightMap = closestMatches.get(policyType); + if (weightMap != null) { + // + // Only need to check first one - as we will ensure there is only one weight + // + Entry>>> firstEntry = + weightMap.entrySet().iterator().next(); + if (policyWeight < firstEntry.getKey()) { + // + // Existing policies have a greater weight, so we will not add it + // + LOGGER.info("{} is lesser weight {} than current policies, will not return it", policyWeight, + firstEntry.getKey()); + } else if (firstEntry.getKey().equals(policyWeight)) { + // + // Same weight - we will add it + // + LOGGER.info("Same weight {}, adding policy", policyWeight); + firstEntry.getValue().add(Pair.of(policyId, policyContent)); + } else { + // + // The weight is greater, so we need to remove the other policies + // and point to this one. + // + LOGGER.info("New policy has greater weight {}, replacing {}", policyWeight, firstEntry.getKey()); + List>> listPolicies = new LinkedList<>(); + listPolicies.add(Pair.of(policyId, policyContent)); + weightMap.clear(); + weightMap.put(policyWeight, listPolicies); + } + } else { + // + // Create a new entry + // + LOGGER.info("New entry {} weight {}", policyType, policyWeight); + List>> listPolicies = new LinkedList<>(); + listPolicies.add(Pair.of(policyId, policyContent)); + Map>>> newWeightMap = new LinkedHashMap<>(); + newWeightMap.put(policyWeight, listPolicies); + closestMatches.put(policyType, newWeightMap); + } + } + @Override public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { // @@ -143,7 +270,8 @@ public class StdMatchableTranslator extends StdBaseTranslator { // Generate the TargetType - the policy should not be evaluated // unless all the matchable properties it cares about are matched. // - newPolicyType.setTarget(generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes)); + Pair pairGenerated = generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes); + newPolicyType.setTarget(pairGenerated.getLeft()); // // Now represent the policy as Json // @@ -157,7 +285,7 @@ public class StdMatchableTranslator extends StdBaseTranslator { // // Add it as an obligation // - addObligation(newPolicyType, jsonPolicy); + addObligation(newPolicyType, policyName, jsonPolicy, pairGenerated.getRight(), toscaPolicy.getType()); // // Now create the Permit Rule. // @@ -196,24 +324,28 @@ public class StdMatchableTranslator extends StdBaseTranslator { * * @param properties Properties section of policy * @param policyTypes Collection of policy Type to find matchable metadata - * @return TargetType object + * @return {@code Pair} Returns a TargetType and a Total Weight of matchables. */ - protected TargetType generateTargetType(Map properties, Collection policyTypes) { + protected Pair generateTargetType(Map properties, + Collection policyTypes) { TargetType targetType = new TargetType(); // // Iterate the properties // + int totalWeight = 0; for (Entry entrySet : properties.entrySet()) { // // Find matchable properties // if (isMatchable(entrySet.getKey(), policyTypes)) { LOGGER.info("Found matchable property {}", entrySet.getKey()); - generateMatchable(targetType, entrySet.getKey(), entrySet.getValue()); + int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue()); + LOGGER.info("Weight is {}", weight); + totalWeight += weight; } } - - return targetType; + LOGGER.info("Total weight is {}", totalWeight); + return Pair.of(targetType, totalWeight); } /** @@ -259,29 +391,33 @@ public class StdMatchableTranslator extends StdBaseTranslator { /** * generateMatchable - Given the object, generates list of MatchType objects and add them - * to the TargetType object. + * to the TargetType object. Returns a weight which is the number of AnyOf's generated. The + * weight can be used to further filter the results for "closest match". * * @param targetType TargetType object to add matches to * @param key Property key * @param value Object is the value - which can be a Collection or single Object - * @return TargetType incoming TargetType returned as a convenience + * @return int Weight of the match. */ @SuppressWarnings("unchecked") - protected TargetType generateMatchable(TargetType targetType, String key, Object value) { + protected int generateMatchable(TargetType targetType, String key, Object value) { + int weight = 0; if (value instanceof Collection) { AnyOfType anyOf = generateMatches((Collection) value, new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key)); if (! anyOf.getAllOf().isEmpty()) { targetType.getAnyOf().add(anyOf); + weight = 1; } } else { AnyOfType anyOf = generateMatches(Arrays.asList(value), new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key)); if (! anyOf.getAllOf().isEmpty()) { targetType.getAnyOf().add(anyOf); + weight = 1; } } - return targetType; + return weight; } /** diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java new file mode 100644 index 00000000..c02d7fb3 --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java @@ -0,0 +1,144 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; + +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.XACML3; +import java.util.Arrays; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.utils.resources.ResourceUtils; + +public class OnapObligationTest { + + String policyJson; + String policyBadJson; + + AttributeAssignment assignmentPolicyId; + AttributeAssignment assignmentPolicy; + AttributeAssignment assignmentBadPolicy; + AttributeAssignment assignmentWeight; + AttributeAssignment assignmentPolicyType; + AttributeAssignment assignmentUnknown; + + Obligation obligation; + + /** + * setup - create test data. + */ + @Before + public void setup() { + policyJson = ResourceUtils.getResourceAsString("test.policy.json"); + policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json"); + + assignmentPolicyId = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(), + policyJson + ); + + assignmentPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyJson + ); + + assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyBadJson + ); + + assignmentWeight = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY.stringValue(), + 0 + ); + + assignmentPolicyType = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY.stringValue(), + "onap.policies.Test" + ); + + assignmentUnknown = TestUtilsCommon.createAttributeAssignment( + "foo:bar", + XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue(), + 10.2 + ); + + obligation = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + Arrays.asList(assignmentPolicyId, assignmentPolicy, assignmentWeight, assignmentPolicyType, + assignmentUnknown)); + } + + @Test + public void testObligation() { + OnapObligation onapObligation = new OnapObligation(obligation); + assertNotNull(onapObligation); + assertThat(onapObligation.getPolicyId()).isEqualTo(assignmentPolicyId.getAttributeValue().getValue()); + assertThat(onapObligation.getPolicyType()).isEqualTo(assignmentPolicyType.getAttributeValue().getValue()); + assertThat(onapObligation.getPolicyContent()).isEqualTo(assignmentPolicy.getAttributeValue().getValue()); + assertThat(onapObligation.getWeight()).isEqualTo(assignmentWeight.getAttributeValue().getValue()); + } + + @Test + public void testSimplePolicy() { + OnapObligation onapObligation = new OnapObligation("my.policy.id", policyJson); + assertNotNull(onapObligation); + assertThat(onapObligation.getPolicyId()).isEqualTo("my.policy.id"); + assertThat(onapObligation.getPolicyContent()).isEqualTo(policyJson); + assertThat(onapObligation.getPolicyType()).isNull(); + assertThat(onapObligation.getWeight()).isNull(); + // + // Create an obligation from it + // + ObligationExpressionType newObligation = onapObligation.generateObligation(); + assertNotNull(newObligation); + assertThat(newObligation.getAttributeAssignmentExpression()).hasSize(2); + } + + + @Test + public void testWeightedPolicy() { + OnapObligation onapObligation = new OnapObligation("my.policy.id", policyJson, "onap.policies.Test", 5); + assertNotNull(onapObligation); + assertThat(onapObligation.getPolicyId()).isEqualTo("my.policy.id"); + assertThat(onapObligation.getPolicyContent()).isEqualTo(policyJson); + assertThat(onapObligation.getPolicyType()).isEqualTo("onap.policies.Test"); + assertThat(onapObligation.getWeight()).isEqualTo(5); + // + // Create an obligation from it + // + ObligationExpressionType newObligation = onapObligation.generateObligation(); + assertNotNull(newObligation); + assertThat(newObligation.getAttributeAssignmentExpression()).hasSize(4); + } + +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java new file mode 100644 index 00000000..ab5dde27 --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common; + +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.IdReference; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.StatusCode; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdAttributeAssignment; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdIdReference; +import com.att.research.xacml.std.StdMutableObligation; +import com.att.research.xacml.std.StdMutableResponse; +import com.att.research.xacml.std.StdMutableResult; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdVersion; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class TestUtilsCommon { + + /** + * createAttributeAssignment. + * + * @param Object can be String, Integer, Double, Boolean + * @param id String attribute id + * @param category String for the attribute category + * @param value Object containing a value + * @return AttributeAssignment object + */ + public static AttributeAssignment createAttributeAssignment(String id, String category, T value) { + StdAttributeValue attributeValue = null; + if (value instanceof String) { + attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_STRING, value); + } else if (value instanceof Integer) { + attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_INTEGER, value); + } else if (value instanceof Double) { + attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_DOUBLE, value); + } else if (value instanceof Boolean) { + attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_BOOLEAN, value); + } else { + throw new IllegalArgumentException("Unsupported value object " + value.getClass()); + } + + return new StdAttributeAssignment(new IdentifierImpl(category), + new IdentifierImpl(id), "", attributeValue); + } + + /** + * createXacmlObligation. + * + * @param id String obligation id + * @param attributeAssignments Collection of AttributeAssignment objects + * @return Obligation object + */ + public static Obligation createXacmlObligation(String id, Collection attributeAssignments) { + return new StdMutableObligation(new IdentifierImpl(id), attributeAssignments); + } + + /** + * createPolicyIdList. + * + * @param ids Map of policy Ids + * @return {@code Collection} objects + * @throws ParseException ParseException + */ + public static Collection createPolicyIdList(Map ids) throws ParseException { + List policyIds = new ArrayList<>(); + + for (Entry entrySet : ids.entrySet()) { + policyIds.add(new StdIdReference(new IdentifierImpl(entrySet.getKey()), + StdVersion.newInstance(entrySet.getValue()))); + } + + return policyIds; + } + + /** + * createXacmlResponse. + * + * @param code StatusCode + * @param decision Decision + * @param obligations Collection of Obligation objects + * @param policyIds Collection of IdReference objects + * @return Response object + */ + public static Response createXacmlResponse(StatusCode code, Decision decision, Collection obligations, + Collection policyIds) { + StdStatus status = new StdStatus(code); + + StdMutableResult result = new StdMutableResult(decision, status); + result.addObligations(obligations); + result.addPolicyIdentifiers(policyIds); + + return new StdMutableResponse(result); + } + +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionaryTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionaryTest.java index b86617c5..b6a7ae20 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionaryTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionaryTest.java @@ -23,7 +23,6 @@ package org.onap.policy.pdp.xacml.application.common; import static org.assertj.core.api.Assertions.assertThatCode; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.lang.reflect.Constructor; @@ -47,10 +46,6 @@ public class ToscaDictionaryTest { constructor.setAccessible(true); constructor.newInstance(); }).doesNotThrowAnyException(); - // - // Probably don't need these as these ID's are used by other components - // - assertNotNull(ToscaDictionary.ID_OBLIGATION_MONITORING_ISSUER); } } diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslatorTest.java index 0b3ce6c3..a7391fab 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslatorTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslatorTest.java @@ -22,30 +22,172 @@ package org.onap.policy.pdp.xacml.application.common.std; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.IdReference; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdStatusCode; +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; +import org.junit.Before; import org.junit.Test; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; public class StdBaseTranslatorTest { + String policyJson; + String policyBadJson; + + AttributeAssignment assignmentPolicyId; + AttributeAssignment assignmentPolicy; + AttributeAssignment assignmentBadPolicy; + AttributeAssignment assignmentWeight; + AttributeAssignment assignmentPolicyType; + AttributeAssignment assignmentUnknown; + + Obligation obligation; + + /** + * beforeSetup - loads and creates objects used later by the tests. + * @throws CoderException CoderException + * + */ + @Before + public void beforeSetup() throws CoderException { + policyJson = ResourceUtils.getResourceAsString("test.policy.json"); + policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json"); + + assignmentPolicyId = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(), + "policy.id" + ); + + assignmentPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyJson + ); + + assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyBadJson + ); + + assignmentWeight = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY.stringValue(), + 0 + ); + + assignmentPolicyType = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY.stringValue(), + "onap.policies.Test" + ); + + assignmentUnknown = TestUtilsCommon.createAttributeAssignment( + "foo:bar", + XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue(), + 10.2 + ); + + obligation = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + Arrays.asList(assignmentPolicyId, assignmentPolicy, assignmentWeight, assignmentPolicyType)); + } + @Test - public void test() { - StdBaseTranslator translator = new StdBaseTranslator(); + public void test() throws ParseException { + StdBaseTranslator translator = new MyStdBaseTranslator(); assertNotNull(translator); assertThatThrownBy(() -> translator.convertPolicy(null)).isInstanceOf(ToscaPolicyConversionException.class); assertNull(translator.convertRequest(null)); + + assertThat(translator.generateAnyOfForPolicyType("foo.bar")).isNotNull(); + assertThat(translator.generateAnyOfForPolicyType("foo.bar").getAllOf().size()).isEqualTo(1); + + assertThat(translator.generateConditionForPolicyType("foo.bar")).isNotNull(); + assertThat(translator.generateConditionForPolicyType("foo.bar").getExpression()).isNotNull(); + + // + // Test the addObligation method + // + PolicySetType policySet = new PolicySetType(); + + translator.addObligation(policySet, "policy.id", policyJson, 0, "foo.bar"); + + assertThat(policySet.getObligationExpressions().getObligationExpression().size()).isEqualTo(1); + assertThat(policySet.getObligationExpressions().getObligationExpression().get(0) + .getAttributeAssignmentExpression().size()).isEqualTo(4); + + PolicyType policy = new PolicyType(); + translator.addObligation(policy, null, policyJson, null, null); + + assertThat(policy.getObligationExpressions().getObligationExpression().size()).isEqualTo(1); + assertThat(policy.getObligationExpressions().getObligationExpression().get(0) + .getAttributeAssignmentExpression().size()).isEqualTo(1); + + RuleType rule = new RuleType(); + translator.addObligation(rule, "policy.id", null, null, "foo.bar"); + + assertThat(rule.getObligationExpressions().getObligationExpression().size()).isEqualTo(1); + assertThat(rule.getObligationExpressions().getObligationExpression().get(0) + .getAttributeAssignmentExpression().size()).isEqualTo(2); + + rule = new RuleType(); + translator.addObligation(rule, null, null, null, null); + + assertThat(rule.getObligationExpressions().getObligationExpression().size()).isEqualTo(1); + assertThat(rule.getObligationExpressions().getObligationExpression().get(0) + .getAttributeAssignmentExpression().size()).isEqualTo(0); + + // + // Should not throw an exception + // + translator.addObligation(new String(), "policy.id", policyJson, null, "foo.bar"); + + // + // Test the response conversion + // + Map ids = new HashMap<>(); + ids.put("onap.policies.Test", "1.0.0"); + Collection policyIds = TestUtilsCommon.createPolicyIdList(ids); + + Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK, + Decision.PERMIT, Arrays.asList(obligation), policyIds); + + DecisionResponse decision = translator.convertResponse(xacmlResponse); + + assertNotNull(decision); + + assertThat(decision.getPolicies()).isNotNull(); + assertThat(decision.getPolicies().size()).isEqualTo(0); } @Test - public void testBadData() throws ToscaPolicyConversionException { + public void testBadData() throws ToscaPolicyConversionException, ParseException { TestTranslator translator = new TestTranslator(); assertThatThrownBy(() -> translator.convertPolicy( @@ -63,11 +205,59 @@ public class StdBaseTranslatorTest { ToscaPolicy policy = new ToscaPolicy(); assertEquals("1.0.0", translator.convertPolicy(policy).getVersion()); + Map ids = new HashMap<>(); + ids.put("onap.policies.Test", "1.0.0"); + Collection policyIds = TestUtilsCommon.createPolicyIdList(ids); + + Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK, + Decision.PERMIT, Arrays.asList(obligation), policyIds); + + DecisionResponse decision = translator.convertResponse(xacmlResponse); + + assertNotNull(decision); + + assertThat(decision.getPolicies()).isNotNull(); + assertThat(decision.getPolicies().size()).isEqualTo(0); + + // + // This will need more work when I fix + // the convertResponse + // + + Obligation badObligation = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + Arrays.asList(assignmentBadPolicy, assignmentUnknown)); + + xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_MISSING_ATTRIBUTE, + Decision.PERMIT, Arrays.asList(badObligation), policyIds); + + decision = translator.convertResponse(xacmlResponse); + + assertNotNull(decision); + + xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK, + Decision.DENY, Arrays.asList(badObligation), policyIds); + + decision = translator.convertResponse(xacmlResponse); + + assertNotNull(decision); + } + + private class MyStdBaseTranslator extends StdBaseTranslator { + + @Override + protected void scanObligations(Collection obligations, DecisionResponse decisionResponse) { + } + } - public class TestTranslator extends StdBaseTranslator { + private class TestTranslator extends StdBaseTranslator { public Map metadata = new HashMap<>(); + @Override + protected void scanObligations(Collection obligations, DecisionResponse decisionResponse) { + } + @Override public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { PolicyType xacmlPolicy = new PolicyType(); diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java new file mode 100644 index 00000000..93124552 --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java @@ -0,0 +1,155 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common.std; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertNotNull; + +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.IdReference; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.std.StdStatusCode; +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; +import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; + +public class StdCombinedPolicyResultsTranslatorTest { + + String policyJson; + String policyBadJson; + + AttributeAssignment assignmentPolicyId; + AttributeAssignment assignmentPolicy; + AttributeAssignment assignmentBadPolicy; + + Obligation obligation; + + /** + * setup - preload policies. + */ + @Before + public void setup() { + policyJson = ResourceUtils.getResourceAsString("test.policy.json"); + policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json"); + + assignmentPolicyId = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(), + policyJson + ); + + assignmentPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyJson + ); + + assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment( + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(), + ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(), + policyBadJson + ); + + + obligation = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + Arrays.asList(assignmentPolicyId, assignmentPolicy)); + + } + + @Test + public void test() throws ParseException { + StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator(); + + assertNotNull(translator); + assertThatThrownBy(() -> translator.convertPolicy(null)).isInstanceOf(ToscaPolicyConversionException.class); + + assertThat(translator.generateTargetType("policy.id", "onap.policy.type", "1.0.0")).isNotNull(); + + Map ids = new HashMap<>(); + ids.put("onap.policies.Test", "1.0.0"); + Collection policyIds = TestUtilsCommon.createPolicyIdList(ids); + + Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK, + Decision.PERMIT, Arrays.asList(obligation), policyIds); + + DecisionResponse decision = translator.convertResponse(xacmlResponse); + + assertNotNull(decision); + + assertThat(decision.getPolicies()).isNotNull(); + assertThat(decision.getPolicies().size()).isEqualTo(1); + } + + @Test + public void testConvert() throws ToscaPolicyConversionException, CoderException { + StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator(); + + assertThatThrownBy(() -> translator.convertPolicy( + new ToscaPolicy())).isInstanceOf(ToscaPolicyConversionException.class) + .hasMessageContaining("missing metadata"); + + StandardCoder coder = new StandardCoder(); + + ToscaServiceTemplate template = coder.decode(policyJson, ToscaServiceTemplate.class); + // + // Make sure all the fields are setup properly + // + JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); + jtst.fromAuthorative(template); + ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + for (Map policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { + for (ToscaPolicy policy : policies.values()) { + translator.convertPolicy(policy); + } + } + } + + @Test + public void testDecision() { + StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator(); + + DecisionRequest decision = new DecisionRequest(); + Map resource = new HashMap<>(); + decision.setResource(resource); + assertNotNull(translator.convertRequest(decision)); + } +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java index d3e362c1..f259c207 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java @@ -96,39 +96,4 @@ public class StdMatchablePolicyRequestTest { } - /* - @Test - public void testCreateInstance_StringValues() { - resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, POLICY_SCOPE); - resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY + "-x", "unused value"); - resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, POLICY_TYPE); - - stdreq = StdMatchablePolicyRequest.createInstance(decreq); - - Collection res = stdreq.getPolicyScopes(); - assertFalse(res.isEmpty()); - assertEquals(POLICY_SCOPE, res.iterator().next()); - - res = stdreq.getPolicyTypes(); - assertFalse(res.isEmpty()); - assertEquals(POLICY_TYPE, res.iterator().next()); - } - - @Test - public void testCreateInstance_Collections() { - resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, Collections.singleton(POLICY_SCOPE)); - resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, Collections.singleton(POLICY_TYPE)); - - stdreq = StdMatchablePolicyRequest.createInstance(decreq); - - Collection res = stdreq.getPolicyScopes(); - assertFalse(res.isEmpty()); - assertEquals(POLICY_SCOPE, res.iterator().next()); - - res = stdreq.getPolicyTypes(); - assertFalse(res.isEmpty()); - assertEquals(POLICY_TYPE, res.iterator().next()); - } -*/ - } diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java index 07317c0a..e9e8814c 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java @@ -20,13 +20,26 @@ package org.onap.policy.pdp.xacml.application.common.std; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.IdReference; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.std.StdStatusCode; import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; @@ -37,6 +50,8 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType; import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -52,10 +67,14 @@ import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardYamlCoder; import org.onap.policy.common.utils.network.NetworkUtil; import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; +import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; import org.slf4j.Logger; @@ -141,7 +160,7 @@ public class StdMatchableTranslatorTest { } @Test - public void test() throws CoderException, ToscaPolicyConversionException { + public void test() throws CoderException, ToscaPolicyConversionException, ParseException { // // Create our translator // @@ -168,15 +187,76 @@ public class StdMatchableTranslatorTest { jtst.fromAuthorative(serviceTemplate); ToscaServiceTemplate completedJtst = jtst.toAuthorative(); // - // Get the policies + // Convert the policy // for (Map policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { for (ToscaPolicy policy : policies.values()) { PolicyType translatedPolicy = translator.convertPolicy(policy); assertNotNull(translatedPolicy); + assertThat(translatedPolicy.getObligationExpressions().getObligationExpression()).hasSize(1); logger.info("Translated policy {} {}", XacmlPolicyUtils.LINE_SEPARATOR, translatedPolicy); + // + // Shortcut to create an obligation, we are just going to steal + // the attributes from the translated policy. + // + List listAttributes = new ArrayList<>(); + ObligationExpressionType xacmlObligation = translatedPolicy.getObligationExpressions() + .getObligationExpression().get(0); + assertThat(xacmlObligation.getAttributeAssignmentExpression()).hasSize(4); + // + // Copy into the list + // + xacmlObligation.getAttributeAssignmentExpression().forEach(assignment -> { + Object value = ((AttributeValueType) assignment.getExpression().getValue()).getContent().get(0); + listAttributes.add(TestUtilsCommon.createAttributeAssignment(assignment.getAttributeId(), + assignment.getCategory(), value)); + }); + // + // Pretend we got multiple policies to match a fictional request + // + Obligation obligation1 = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + listAttributes); + Obligation obligation2 = TestUtilsCommon.createXacmlObligation( + ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(), + listAttributes); + // + // Should ignore this obligation + // + Obligation obligation3 = TestUtilsCommon.createXacmlObligation( + "nobody:cares", + listAttributes); + // + // Create a test XACML Response + // + Map ids = new HashMap<>(); + ids.put("onap.policies.Test", "1.0.0"); + Collection policyIds = TestUtilsCommon.createPolicyIdList(ids); + + com.att.research.xacml.api.Response xacmlResponse = TestUtilsCommon.createXacmlResponse( + StdStatusCode.STATUS_CODE_OK, Decision.PERMIT, + Arrays.asList(obligation1, obligation2, obligation3), policyIds); + // + // Test the response + // + DecisionResponse decisionResponse = translator.convertResponse(xacmlResponse); + assertNotNull(decisionResponse); + assertThat(decisionResponse.getPolicies()).hasSize(1); } } + // + // Test request decisions + // + DecisionRequest decisionRequest = new DecisionRequest(); + decisionRequest.setAction("action"); + decisionRequest.setOnapComponent("onap-component"); + decisionRequest.setOnapName("onap"); + Map resource = new HashMap<>(); + resource.put("matchableString", "I should be matched"); + decisionRequest.setResource(resource); + Request xacmlRequest = translator.convertRequest(decisionRequest); + assertNotNull(xacmlRequest); + assertThat(xacmlRequest.getRequestAttributes()).hasSize(3); } /** diff --git a/applications/common/src/test/resources/test.policy.bad.json b/applications/common/src/test/resources/test.policy.bad.json new file mode 100644 index 00000000..6bc06c3b --- /dev/null +++ b/applications/common/src/test/resources/test.policy.bad.json @@ -0,0 +1,17 @@ +{ + "tosca_definitions_version": "tosca_simple_yaml_1_0_0", + "topology_template": { + "policies": [ + { + "Test.policy": { + "type": "onap.policies.Test", + "type_version": "1.0.0", + "version": "1.0.0", + "properties": { + "foo": "bar" + } + } + } + ] + } +} diff --git a/applications/common/src/test/resources/test.policy.json b/applications/common/src/test/resources/test.policy.json new file mode 100644 index 00000000..f1529387 --- /dev/null +++ b/applications/common/src/test/resources/test.policy.json @@ -0,0 +1,21 @@ +{ + "tosca_definitions_version": "tosca_simple_yaml_1_0_0", + "topology_template": { + "policies": [ + { + "Test.policy": { + "type": "onap.policies.Test", + "type_version": "1.0.0", + "version": "1.0.0", + "metadata": { + "policy-id": "Test.policy", + "policy-version": 1 + }, + "properties": { + "foo": "bar" + } + } + } + ] + } +} -- cgit 1.2.3-korg