diff options
23 files changed, 1321 insertions, 1101 deletions
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 c8dab3a8..921babb8 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 @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -82,6 +82,10 @@ public final class ToscaDictionary { new IdentifierImpl(ID_URN_ONAP, "guard:target:min"); public static final Identifier ID_RESOURCE_GUARD_MAX = new IdentifierImpl(ID_URN_ONAP, "guard:target:max"); + public static final Identifier ID_RESOURCE_GUARD_TIMESTART = + new IdentifierImpl(ID_URN_ONAP, "guard.target:timestart"); + public static final Identifier ID_RESOURCE_GUARD_TIMEEND = + new IdentifierImpl(ID_URN_ONAP, "guard.target:timeend"); /* * This id specifically for guard is provided by the diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java index cdf5404b..f1d3d5e3 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -23,10 +23,14 @@ package org.onap.policy.pdp.xacml.application.common; import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.XACML3; import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType; 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.MatchType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory; +import org.apache.commons.lang3.StringUtils; /** * This class contains static methods of helper classes to convert TOSCA policies @@ -36,6 +40,7 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; * */ public final class ToscaPolicyTranslatorUtils { + private static final ObjectFactory factory = new ObjectFactory(); private ToscaPolicyTranslatorUtils() { super(); @@ -99,4 +104,66 @@ public final class ToscaPolicyTranslatorUtils { } return allOf; } + + /** + * Takes start and end time interval and generates an ApplyType for it. + * + * @param start ISO8601 timestamp + * @param end ISO8601 timestamp + * @return ApplyType + */ + public static ApplyType generateTimeInRange(String start, String end) { + if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) { + return null; + } + + AttributeDesignatorType designator = new AttributeDesignatorType(); + designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue()); + designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue()); + designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); + + AttributeValueType valueStart = new AttributeValueType(); + valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); + valueStart.getContent().add(start); + + AttributeValueType valueEnd = new AttributeValueType(); + valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); + valueEnd.getContent().add(end); + + + ApplyType applyOneAndOnly = new ApplyType(); + applyOneAndOnly.setDescription("Unbag the current time"); + applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue()); + applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); + + ApplyType applyTimeInRange = new ApplyType(); + applyTimeInRange.setDescription("return true if current time is in range."); + applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue()); + applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly)); + applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart)); + applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd)); + + return applyTimeInRange; + } + + /** + * Parses an integer value from the string. + * + * @param strInteger String representation of integer + * @return Integer object + */ + public static Integer parseInteger(String strInteger) { + Integer theInt = null; + try { + theInt = Integer.parseInt(strInteger); + } catch (NumberFormatException e) { + try { + Double dblLimit = Double.parseDouble(strInteger); + theInt = dblLimit.intValue(); + } catch (NumberFormatException e1) { + return null; + } + } + return theInt; + } } diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/operationshistory/GetOperationOutcomePip.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/operationshistory/GetOperationOutcomePip.java index f2339b11..56d68d55 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/operationshistory/GetOperationOutcomePip.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/operationshistory/GetOperationOutcomePip.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -32,7 +32,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.Collection; import java.util.Properties; - +import javax.persistence.NoResultException; import javax.persistence.Persistence; import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; @@ -101,14 +101,14 @@ public class GetOperationOutcomePip extends StdOnapPip { // Determine if the issuer is correct // if (Strings.isNullOrEmpty(pipRequest.getIssuer())) { - logger.debug("issuer is null - returning empty response"); + logger.error("issuer is null - returning empty response"); // // We only respond to ourself as the issuer // return StdPIPResponse.PIP_RESPONSE_EMPTY; } if (! pipRequest.getIssuer().startsWith(ToscaDictionary.GUARD_ISSUER_PREFIX)) { - logger.debug("Issuer does not start with guard"); + logger.error("Issuer does not start with guard"); // // We only respond to ourself as the issuer // @@ -161,9 +161,11 @@ public class GetOperationOutcomePip extends StdOnapPip { .setParameter(2, target) .setMaxResults(1) .getSingleResult(); + } catch (NoResultException e) { + logger.trace("No results", e); } catch (Exception e) { - logger.error("Typed query failed ", e); - return null; + logger.error("Typed query failed", e); } + return null; } } diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java index 6fdb8772..8b85a0df 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -22,6 +22,7 @@ package org.onap.policy.pdp.xacml.application.common; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertTrue; import java.lang.reflect.Constructor; @@ -39,4 +40,9 @@ public class ToscaPolicyTranslatorUtilsTest { } + @Test + public void testTimeInRange() { + assertThat(ToscaPolicyTranslatorUtils.generateTimeInRange("T00:00:00Z", "T08:00:00Z")).isNotNull(); + } + } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java index 0073f74e..b4e431c4 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -42,23 +42,22 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplication.class); private static final String STRING_VERSION100 = "1.0.0"; private List<ToscaPolicyTypeIdentifier> supportedPolicyTypes = new ArrayList<>(); - private LegacyGuardTranslator legacyTranslator = new LegacyGuardTranslator(); + private GuardTranslator guardTranslator = new GuardTranslator(); private CoordinationGuardTranslator coordinationTranslator = new CoordinationGuardTranslator(); - /** * Constructor. * */ public GuardPdpApplication() { this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", + GuardTranslator.POLICYTYPE_FREQUENCY, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", + GuardTranslator.POLICYTYPE_MINMAX, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", + GuardTranslator.POLICYTYPE_BLACKLIST, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", @@ -101,8 +100,8 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { LOGGER.debug("returning coordinationTranslator"); return coordinationTranslator; } else { - LOGGER.debug("returning legacyTranslator"); - return legacyTranslator; + LOGGER.debug("returning guardTranslator"); + return guardTranslator; } } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java index bfbe4f64..51d8f0ed 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -39,7 +39,7 @@ import org.onap.policy.models.decisions.concepts.DecisionRequest; @Setter @ToString @XACMLRequest(ReturnPolicyIdList = true) -public class LegacyGuardPolicyRequest { +public class GuardPolicyRequest { private static final String STR_GUARD = "guard"; @@ -73,14 +73,7 @@ public class LegacyGuardPolicyRequest { @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:vf-count") private Integer vfCount; - @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:min") - private Integer min; - - @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:max") - private Integer max; - - - public LegacyGuardPolicyRequest() { + public GuardPolicyRequest() { super(); } @@ -91,11 +84,11 @@ public class LegacyGuardPolicyRequest { * @return StdMetadataPolicyRequest */ @SuppressWarnings("unchecked") - public static LegacyGuardPolicyRequest createInstance(DecisionRequest decisionRequest) { + public static GuardPolicyRequest createInstance(DecisionRequest decisionRequest) { // // Create our return object // - LegacyGuardPolicyRequest request = new LegacyGuardPolicyRequest(); + GuardPolicyRequest request = new GuardPolicyRequest(); // // Add the subject attributes // @@ -140,14 +133,12 @@ public class LegacyGuardPolicyRequest { request.targetId = guard.get("target").toString(); } if (guard.containsKey("vfCount")) { + // + // TODO this can potentially throw a NumberFormatException. Fix this to + // throw the exception when you fix the ConvertRequest to throw exceptions also. + // request.vfCount = Integer.decode(guard.get("vfCount").toString()); } - if (guard.containsKey("min")) { - request.min = Integer.decode(guard.get("min").toString()); - } - if (guard.containsKey("max")) { - request.max = Integer.decode(guard.get("max").toString()); - } return request; } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java new file mode 100644 index 00000000..ebcae8dd --- /dev/null +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java @@ -0,0 +1,505 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.xacml.pdp.application.guard; + +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Identifier; +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.att.research.xacml.std.annotations.RequestParser; +import java.util.Collection; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; +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.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.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.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.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; +import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GuardTranslator implements ToscaPolicyTranslator { + private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslator.class); + + // + // common guard property fields + // + public static final String FIELD_ACTOR = "actor"; + public static final String FIELD_OPERATION = "operation"; + public static final String FIELD_CONTROLLOOP = "id"; + public static final String FIELD_TIMERANGE = "timeRange"; + + // + // frequency property fields + // + public static final String FIELD_TIMEWINDOW = "timeWindow"; + public static final String FIELD_TIMEUNITS = "timeUnits"; + public static final String FIELD_LIMIT = "limit"; + + // + // minmax property fields + // + public static final String FIELD_TARGET = "target"; + public static final String FIELD_MIN = "min"; + public static final String FIELD_MAX = "max"; + + // + // blacklist property fields + // + public static final String FIELD_BLACKLIST = "blacklist"; + + public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter"; + public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax"; + public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist"; + + public GuardTranslator() { + super(); + } + + /** + * Convert the policy. + */ + public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + // + // Policy name should be at the root + // + String policyName = toscaPolicy.getMetadata().get("policy-id"); + // + // Set it as the policy ID + // + PolicyType newPolicyType = new PolicyType(); + newPolicyType.setPolicyId(policyName); + // + // Optional description + // + newPolicyType.setDescription(toscaPolicy.getDescription()); + // + // There should be a metadata section + // + this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata()); + // + // Generate the TargetType - add true if not blacklist + // + newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(), + ! POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType()))); + // + // Add specific's per guard policy type + // + if (POLICYTYPE_FREQUENCY.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); + generateFrequencyRules(toscaPolicy, policyName, newPolicyType); + } else if (POLICYTYPE_MINMAX.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); + generateMinMaxRules(toscaPolicy, policyName, newPolicyType); + } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue()); + generateBlacklistRules(toscaPolicy, policyName, newPolicyType); + } else { + throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType()); + } + return newPolicyType; + } + + /** + * Convert Request. + */ + public Request convertRequest(DecisionRequest request) { + LOGGER.info("Converting Request {}", request); + try { + return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request)); + } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) { + LOGGER.error("Failed to convert DecisionRequest: {}", e); + } + // + // TODO throw exception + // + return null; + } + + /** + * Convert response. + */ + public DecisionResponse convertResponse(Response xacmlResponse) { + LOGGER.info("Converting Response {}", xacmlResponse); + DecisionResponse decisionResponse = new DecisionResponse(); + // + // Iterate through all the results + // + for (Result xacmlResult : xacmlResponse.getResults()) { + // + // Check the result + // + if (xacmlResult.getDecision() == Decision.PERMIT) { + // + // Just simply return a Permit response + // + decisionResponse.setStatus(Decision.PERMIT.toString()); + } else if (xacmlResult.getDecision() == Decision.DENY) { + // + // Just simply return a Deny response + // + decisionResponse.setStatus(Decision.DENY.toString()); + } else { + // + // There is no guard policy, so we return a permit + // + decisionResponse.setStatus(Decision.PERMIT.toString()); + } + } + + return decisionResponse; + } + + /** + * From the TOSCA metadata section, pull in values that are needed into the XACML policy. + * + * @param policy Policy Object to store the metadata + * @param map The Metadata TOSCA Map + * @return Same Policy Object + */ + protected PolicyType fillMetadataSection(PolicyType policy, Map<String, String> map) { + // + // NOTE: The models code ensures the metadata section ALWAYS exists + // + // + // Add in the Policy Version + // + policy.setVersion(map.get("policy-version")); + return policy; + } + + /** + * Generate the targettype for the policy. Optional to add MatchType for the target. eg. the + * blacklist policy type uses the target in a different manner. + * + * @param properties TOSCA properties object + * @param addTargets true to go ahead and add target to the match list. + * @return TargetType object + * @throws ToscaPolicyConversionException if there is a missing property + */ + protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets) + throws ToscaPolicyConversionException { + // + // Go through potential properties + // + AllOfType allOf = new AllOfType(); + if (properties.containsKey(FIELD_ACTOR)) { + addMatch(allOf, properties.get(FIELD_ACTOR), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR); + } + if (properties.containsKey(FIELD_OPERATION)) { + addMatch(allOf, properties.get(FIELD_OPERATION), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE); + } + if (addTargets && properties.containsKey(FIELD_TARGET)) { + addMatch(allOf, properties.get(FIELD_TARGET), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); + } + if (properties.containsKey(FIELD_CONTROLLOOP)) { + addMatch(allOf, properties.get(FIELD_CONTROLLOOP), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME); + } + if (properties.containsKey(FIELD_TIMERANGE)) { + addTimeRangeMatch(allOf, properties.get(FIELD_TIMERANGE)); + } + // + // Create target + // + TargetType target = new TargetType(); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + target.getAnyOf().add(anyOf); + return target; + } + + @SuppressWarnings("unchecked") + protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) { + if (value instanceof String) { + if (".*".equals(value.toString())) { + // + // There's no point to even have a match + // + return allOf; + } else { + // + // Exact match + // + MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + value, + XACML3.ID_DATATYPE_STRING, + attributeId, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(match); + } + return allOf; + } + if (value instanceof Collection) { + ((Collection<String>) value).forEach(val -> { + MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + val, + XACML3.ID_DATATYPE_STRING, + attributeId, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(match); + }); + } + return allOf; + } + + @SuppressWarnings("rawtypes") + protected void addTimeRangeMatch(AllOfType allOf, Object timeRange) + throws ToscaPolicyConversionException { + if (! (timeRange instanceof Map)) { + throw new ToscaPolicyConversionException("timeRange is not a map object " + timeRange.getClass()); + } + + MatchType matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL, + ((Map) timeRange).get("start_time").toString(), + XACML3.ID_DATATYPE_TIME, + XACML3.ID_ENVIRONMENT_CURRENT_TIME, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(matchStart); + + MatchType matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL, + ((Map) timeRange).get("end_time").toString(), + XACML3.ID_DATATYPE_TIME, + XACML3.ID_ENVIRONMENT_CURRENT_TIME, + XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT); + + allOf.getMatch().add(matchEnd); + } + + protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // We must have the limit + // + if (! toscaPolicy.getProperties().containsKey(FIELD_LIMIT)) { + throw new ToscaPolicyConversionException("Missing property limit"); + } + // + // See if its possible to generate a count + // + Integer limit = ToscaPolicyTranslatorUtils.parseInteger( + toscaPolicy.getProperties().get(FIELD_LIMIT).toString()); + if (limit == null) { + throw new ToscaPolicyConversionException("Missing limit value"); + } + String timeWindow = null; + if (toscaPolicy.getProperties().containsKey(FIELD_TIMEWINDOW)) { + Integer intTimeWindow = ToscaPolicyTranslatorUtils.parseInteger( + toscaPolicy.getProperties().get(FIELD_TIMEWINDOW).toString()); + if (intTimeWindow == null) { + throw new ToscaPolicyConversionException("timeWindow is not an integer"); + } + timeWindow = intTimeWindow.toString(); + } + String timeUnits = null; + if (toscaPolicy.getProperties().containsKey(FIELD_TIMEUNITS)) { + timeUnits = toscaPolicy.getProperties().get(FIELD_TIMEUNITS).toString(); + } + // + // Generate a count + // + final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits); + // + // Create our condition + // + final ConditionType condition = new ConditionType(); + condition.setExpression(new ObjectFactory().createApply(countCheck)); + + // + // Now we can create our rule + // + RuleType frequencyRule = new RuleType(); + frequencyRule.setDescription("Frequency limit permit rule"); + frequencyRule.setRuleId(policyName + ":frequency"); + frequencyRule.setEffect(EffectType.PERMIT); + frequencyRule.setTarget(new TargetType()); + // + // Add the condition + // + frequencyRule.setCondition(condition); + // + // Add the rule to the policy + // + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule); + } + + protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) { + AttributeDesignatorType designator = new AttributeDesignatorType(); + designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue()); + designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); + designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); + // + // Setup issuer - used by the operations PIP to determine + // how to do the database query. + // + String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX + + CountRecentOperationsPip.ISSUER_NAME + + ":tw:" + timeWindow + ":" + timeUnits; + designator.setIssuer(issuer); + + AttributeValueType valueLimit = new AttributeValueType(); + valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); + // + // Yes really use toString(), the marshaller will + // throw an exception if this is an integer object + // and not a string. + // + valueLimit.getContent().add(limit.toString()); + + ObjectFactory factory = new ObjectFactory(); + + ApplyType applyOneAndOnly = new ApplyType(); + applyOneAndOnly.setDescription("Unbag the limit"); + applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); + applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); + + ApplyType applyLessThan = new ApplyType(); + applyLessThan.setDescription("return true if current count is less than."); + applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue()); + applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly)); + applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit)); + + return applyLessThan; + } + + protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // Add the target + // + if (! toscaPolicy.getProperties().containsKey(FIELD_TARGET)) { + throw new ToscaPolicyConversionException("Missing target field in minmax policy"); + } + MatchType matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + toscaPolicy.getProperties().get(FIELD_TARGET).toString(), + XACML3.ID_DATATYPE_STRING, + ToscaDictionary.ID_RESOURCE_GUARD_TARGETID, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + // + // For the min, if the # of instances is less than the minimum + // then allow the scale. + // + Integer min = null; + if (toscaPolicy.getProperties().containsKey(FIELD_MIN)) { + min = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MIN).toString()); + MatchType matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_INTEGER_GREATER_THAN, + min.toString(), + XACML3.ID_DATATYPE_INTEGER, + ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add( + generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum")); + } + Integer max = null; + if (toscaPolicy.getProperties().containsKey(FIELD_MAX)) { + max = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MAX).toString()); + MatchType matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_INTEGER_GREATER_THAN, + max.toString(), + XACML3.ID_DATATYPE_INTEGER, + ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add( + generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum")); + } + // + // Do we have at least a min or max? + // + if (min == null && max == null) { + throw new ToscaPolicyConversionException("Missing min or max field in minmax policy"); + } + } + + protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) { + AllOfType allOf = new AllOfType(); + allOf.getMatch().add(matchTarget); + allOf.getMatch().add(matchMinOrMax); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + TargetType target = new TargetType(); + target.getAnyOf().add(anyOf); + RuleType minMaxRule = new RuleType(); + minMaxRule.setEffect(EffectType.PERMIT); + minMaxRule.setDescription(desc); + minMaxRule.setRuleId(ruleId); + minMaxRule.setTarget(target); + return minMaxRule; + } + + protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // Validate the blacklist exists + // + if (! toscaPolicy.getProperties().containsKey(FIELD_BLACKLIST)) { + throw new ToscaPolicyConversionException("Missing blacklist field"); + } + final AllOfType allOf = new AllOfType(); + this.addMatch(allOf, toscaPolicy.getProperties().get(FIELD_BLACKLIST), + ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); + // + // Create our rule and add the target + // + RuleType blacklistRule = new RuleType(); + blacklistRule.setEffect(EffectType.DENY); + blacklistRule.setDescription("blacklist the entities"); + blacklistRule.setRuleId(policyName + ":blacklist"); + TargetType target = new TargetType(); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + target.getAnyOf().add(anyOf); + blacklistRule.setTarget(target); + // + // Add the rule to the policy + // + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule); + } + +} diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java deleted file mode 100644 index 0cb06ea0..00000000 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java +++ /dev/null @@ -1,786 +0,0 @@ -/*- - * ============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.xacml.pdp.application.guard; - -import com.att.research.xacml.api.DataTypeException; -import com.att.research.xacml.api.Decision; -import com.att.research.xacml.api.Identifier; -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.att.research.xacml.std.annotations.RequestParser; - -import java.util.Collection; -import java.util.Map; - -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; -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.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.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.ToscaDictionary; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; -import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LegacyGuardTranslator implements ToscaPolicyTranslator { - - private static final Logger LOGGER = LoggerFactory.getLogger(LegacyGuardTranslator.class); - - private static final String FIELD_GUARD_ACTIVE_START = "guardActiveStart"; - private static final String FIELD_GUARD_ACTIVE_END = "guardActiveEnd"; - private static final String FIELD_TARGET = "targets"; - private static final String DESC_DEFAULT = "Default is to PERMIT if the policy matches."; - private static final String ID_RULE = ":rule"; - - public LegacyGuardTranslator() { - super(); - } - - @Override - public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { - // - // Policy name should be at the root - // - String policyName = toscaPolicy.getMetadata().get("policy-id"); - // - // Set it as the policy ID - // - PolicyType newPolicyType = new PolicyType(); - newPolicyType.setPolicyId(policyName); - // - // Optional description - // - newPolicyType.setDescription(toscaPolicy.getDescription()); - // - // There should be a metadata section - // - this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata()); - // - // Set the combining rule - // - newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); - // - // Generate the TargetType - add true if not blacklist - // - newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(), - ! "onap.policies.controlloop.guard.Blacklist".equals(toscaPolicy.getType()))); - // - // Now create the Permit Rule - // - RuleType rule = generatePermitRule(policyName, toscaPolicy.getType(), toscaPolicy.getProperties()); - // - // Check if we were able to create the rule - // - if (rule == null) { - LOGGER.error("Failed to create rule"); - return null; - } - // - // Add the rule to the policy - // - newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule); - // - // Return our new policy - // - return newPolicyType; - } - - @Override - public Request convertRequest(DecisionRequest request) { - LOGGER.info("Converting Request {}", request); - try { - return RequestParser.parseRequest(LegacyGuardPolicyRequest.createInstance(request)); - } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) { - LOGGER.error("Failed to convert DecisionRequest: {}", e); - } - // - // TODO throw exception - // - return null; - } - - @Override - public DecisionResponse convertResponse(Response xacmlResponse) { - LOGGER.info("Converting Response {}", xacmlResponse); - DecisionResponse decisionResponse = new DecisionResponse(); - // - // Iterate through all the results - // - for (Result xacmlResult : xacmlResponse.getResults()) { - // - // Check the result - // - if (xacmlResult.getDecision() == Decision.PERMIT) { - // - // Just simply return a Permit response - // - decisionResponse.setStatus(Decision.PERMIT.toString()); - } - if (xacmlResult.getDecision() == Decision.DENY) { - // - // Just simply return a Deny response - // - decisionResponse.setStatus(Decision.DENY.toString()); - } - if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) { - // - // There is no guard policy, so we return a permit - // - decisionResponse.setStatus(Decision.PERMIT.toString()); - } - } - - return decisionResponse; - } - - /** - * From the TOSCA metadata section, pull in values that are needed into the XACML policy. - * - * @param policy Policy Object to store the metadata - * @param map The Metadata TOSCA Map - * @return Same Policy Object - * @throws ToscaPolicyConversionException If there is something missing from the metadata - */ - protected PolicyType fillMetadataSection(PolicyType policy, - Map<String, String> map) throws ToscaPolicyConversionException { - if (! map.containsKey("policy-id")) { - throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-id"); - } else { - // - // Do nothing here - the XACML PolicyId is used from TOSCA Policy Name field - // - } - if (! map.containsKey("policy-version")) { - throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version"); - } else { - // - // Add in the Policy Version - // - policy.setVersion(map.get("policy-version")); - } - return policy; - } - - protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets) { - // - // Go through potential properties - // - AllOfType allOf = new AllOfType(); - if (properties.containsKey("actor")) { - addMatch(allOf, properties.get("actor"), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR); - } - if (properties.containsKey("recipe")) { - addMatch(allOf, properties.get("recipe"), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE); - } - if (addTargets && properties.containsKey(FIELD_TARGET)) { - addMatch(allOf, properties.get(FIELD_TARGET), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); - } - if (properties.containsKey("clname")) { - addMatch(allOf, properties.get("clname"), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME); - } - // - // Create target - // - TargetType target = new TargetType(); - AnyOfType anyOf = new AnyOfType(); - anyOf.getAllOf().add(allOf); - target.getAnyOf().add(anyOf); - return target; - } - - private static AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) { - if (value instanceof String) { - if (".*".equals(value.toString())) { - // - // There's no point to even have a match - // - return allOf; - } else { - // - // Exact match - // - MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( - XACML3.ID_FUNCTION_STRING_EQUAL, - value, - XACML3.ID_DATATYPE_STRING, - attributeId, - XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); - - allOf.getMatch().add(match); - } - return allOf; - } - if (value instanceof Collection) { - // - // TODO support a collection of that attribute - // - } - return allOf; - } - - private static RuleType generatePermitRule(String policyName, String policyType, Map<String, Object> properties) - throws ToscaPolicyConversionException { - // - // Now determine which policy type we are generating - // - if ("onap.policies.controlloop.guard.FrequencyLimiter".equals(policyType)) { - return generateFrequencyPermit(policyName, properties); - } else if ("onap.policies.controlloop.guard.MinMax".equals(policyType)) { - return generateMinMaxPermit(policyName, properties); - } else if ("onap.policies.controlloop.guard.Blacklist".equals(policyType)) { - return generateBlacklistPermit(policyName, properties); - } - LOGGER.error("Missing policy type in the policy"); - return null; - } - - private static RuleType generateFrequencyPermit(String policyName, Map<String, Object> properties) - throws ToscaPolicyConversionException { - // - // See if its possible to generate a count - // - Integer limit = parseInteger(properties.get("limit").toString()); - if (limit == null) { - LOGGER.error("Must have a limit value for frequency guard policy to be created"); - return null; - } - // - // Get the properties that are common among guards - // - String timeWindow = null; - if (properties.containsKey("timeWindow")) { - Integer intTimeWindow = parseInteger(properties.get("timeWindow").toString()); - if (intTimeWindow == null) { - throw new ToscaPolicyConversionException("timeWindow is not an integer"); - } - timeWindow = intTimeWindow.toString(); - } - String timeUnits = null; - if (properties.containsKey("timeUnits")) { - timeUnits = properties.get("timeUnits").toString(); - } - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // Generate a count - // - final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits); - // - // Now combine into an And - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if time range and count checks are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange)); - applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck)); - - // - // Create our condition - // - final ConditionType condition = new ConditionType(); - condition.setExpression(new ObjectFactory().createApply(applyAnd)); - - // - // Now we can create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Add the condition - // - permit.setCondition(condition); - // - // Done - // - return permit; - } - - private static RuleType generateMinMaxPermit(String policyName, Map<String, Object> properties) { - // - // Get the properties that are common among guards - // - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // See if its possible to generate a count - // - Integer min = null; - if (properties.containsKey("min")) { - min = parseInteger(properties.get("min").toString()); - } - Integer max = null; - if (properties.containsKey("max")) { - max = parseInteger(properties.get("max").toString()); - } - final ApplyType minApply = generateMinCheck(min); - final ApplyType maxApply = generateMaxCheck(max); - // - // Make sure we have at least something to check here, - // otherwise there really is no point to this policy. - // - if (timeRange == null && minApply == null && maxApply == null) { - return null; - } - // - // Create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Create the condition - // - permit.setCondition(createCondition(timeRange, minApply, maxApply)); - // - // Done - // - return permit; - } - - private static ConditionType createCondition(ApplyType timeRange, ApplyType minApply, ApplyType maxApply) { - final ConditionType condition = new ConditionType(); - // - // Check if we have all the fields (this can be a little - // ugly) but the ultimate goal is to simplify the policy - // condition to only check for necessary attributes. - // - ObjectFactory factory = new ObjectFactory(); - if (timeRange != null && minApply != null && maxApply != null) { - // - // All 3 must apply - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if all the apply's are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(factory.createApply(timeRange)); - applyAnd.getExpression().add(factory.createApply(minApply)); - applyAnd.getExpression().add(factory.createApply(maxApply)); - // - // Add into the condition - // - condition.setExpression(factory.createApply(applyAnd)); - - return condition; - } - // - // At least one of these applies is null. We need at least - // two to require the And apply. Otherwise there is no need - // for an outer And apply as the single condition can work - // on its own. - // - if (timeRange != null && minApply == null && maxApply == null) { - // - // Only the time range check is necessary - // - condition.setExpression(factory.createApply(timeRange)); - } else if (timeRange == null && minApply != null && maxApply == null) { - // - // Only the min check is necessary - // - condition.setExpression(factory.createApply(minApply)); - } else if (timeRange == null && minApply == null) { - // - // Only the max check is necessary - // - condition.setExpression(factory.createApply(maxApply)); - } else { - // - // Ok we will need an outer And and have at least the - // time range and either min or max check - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if all the apply's are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - if (timeRange != null) { - applyAnd.getExpression().add(factory.createApply(timeRange)); - } - if (minApply != null) { - applyAnd.getExpression().add(factory.createApply(minApply)); - } - if (maxApply != null) { - applyAnd.getExpression().add(factory.createApply(maxApply)); - } - // - // Add into the condition - // - condition.setExpression(factory.createApply(applyAnd)); - } - return condition; - } - - private static RuleType generateBlacklistPermit(String policyName, Map<String, Object> properties) { - // - // Generate target - // - if (! properties.containsKey(FIELD_TARGET)) { - LOGGER.error("Missing target for blacklist policy"); - return null; - } - final ApplyType targetApply = generateTargetApply(properties.get(FIELD_TARGET)); - // - // Get the properties that are common among guards - // - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // Create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Create our condition - // - ObjectFactory factory = new ObjectFactory(); - ApplyType innerApply; - if (timeRange != null) { - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("Combine the timeRange with target to create AND"); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(factory.createApply(timeRange)); - applyAnd.getExpression().add(factory.createApply(targetApply)); - // - // Now we need to NOT this so the permit happens - // - ApplyType applyNot = new ApplyType(); - applyNot.setDescription("This should be false for a permit."); - applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue()); - applyNot.getExpression().add(factory.createApply(applyAnd)); - innerApply = applyNot; - } else { - // - // Just the target is needed - // - ApplyType applyNot = new ApplyType(); - applyNot.setDescription("This should be false for a permit."); - applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue()); - applyNot.getExpression().add(factory.createApply(targetApply)); - innerApply = applyNot; - } - // - // Create our condition - // - final ConditionType condition = new ConditionType(); - // - // Add into the condition - // - condition.setExpression(factory.createApply(innerApply)); - // - // Add the condition - // - permit.setCondition(condition); - return permit; - } - - private static ApplyType generateTimeInRange(String start, String end) { - if (start == null || end == null) { - LOGGER.warn("Missing time range start {} end {}", start, end); - return null; - } - if (start.isEmpty() || end.isEmpty()) { - LOGGER.warn("Empty time range start {} end {}", start, end); - return null; - } - - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - - AttributeValueType valueStart = new AttributeValueType(); - valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - valueStart.getContent().add(start); - - AttributeValueType valueEnd = new AttributeValueType(); - valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - valueEnd.getContent().add(end); - - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the current time"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyTimeInRange = new ApplyType(); - applyTimeInRange.setDescription("return true if current time is in range."); - applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue()); - applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly)); - applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart)); - applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd)); - - return applyTimeInRange; - } - - private static ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) { - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Setup issuer - // - String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX - + CountRecentOperationsPip.ISSUER_NAME - + ":tw:" + timeWindow + ":" + timeUnits; - designator.setIssuer(issuer); - - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(limit.toString()); - - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the limit"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyLessThan = new ApplyType(); - applyLessThan.setDescription("return true if current count is less than."); - applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue()); - applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly)); - applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyLessThan; - } - - private static ApplyType generateMinCheck(Integer min) { - if (min == null) { - return null; - } - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // - // - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(min.toString()); - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the min"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyGreaterThanEqual = new ApplyType(); - applyGreaterThanEqual.setDescription("return true if current count is greater than or equal."); - applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue()); - applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyGreaterThanEqual; - } - - private static ApplyType generateMaxCheck(Integer max) { - if (max == null) { - return null; - } - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // - // - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(max.toString()); - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the min"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyLessThanEqual = new ApplyType(); - applyLessThanEqual.setDescription("return true if current count is less than or equal."); - applyLessThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue()); - applyLessThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyLessThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyLessThanEqual; - } - - @SuppressWarnings("unchecked") - private static ApplyType generateTargetApply(Object targetObject) { - ObjectFactory factory = new ObjectFactory(); - // - // Create a bag of values - // - ApplyType applyStringBag = new ApplyType(); - applyStringBag.setDescription("Bag the target values"); - applyStringBag.setFunctionId(XACML3.ID_FUNCTION_STRING_BAG.stringValue()); - if (targetObject instanceof Collection) { - for (Object target : ((Collection<Object>) targetObject)) { - if (! (target instanceof String)) { - LOGGER.error("Collection of unsupported objects {}", target.getClass()); - return null; - } - AttributeValueType value = new AttributeValueType(); - value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - value.getContent().add(target.toString()); - applyStringBag.getExpression().add(factory.createAttributeValue(value)); - } - } else if (targetObject instanceof String) { - AttributeValueType value = new AttributeValueType(); - value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - value.getContent().add(targetObject.toString()); - applyStringBag.getExpression().add(factory.createAttributeValue(value)); - } else { - LOGGER.warn("Unsupported object for target {}", targetObject.getClass()); - return null; - } - // - // Create our designator - // - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - // - // Create apply for our AnyOf - // - ApplyType applyAnyOf = new ApplyType(); - applyAnyOf.setDescription("Find designator as anyof the possible values"); - applyAnyOf.setFunctionId(XACML3.ID_FUNCTION_ANY_OF.stringValue()); - applyAnyOf.getExpression().add(factory.createAttributeDesignator(designator)); - applyAnyOf.getExpression().add(factory.createApply(applyStringBag)); - return applyAnyOf; - } - - private static Integer parseInteger(String strInteger) { - Integer theInt = null; - try { - theInt = Integer.parseInt(strInteger); - } catch (NumberFormatException e) { - LOGGER.warn("Expecting an integer", e); - try { - Double dblLimit = Double.parseDouble(strInteger); - theInt = dblLimit.intValue(); - } catch (NumberFormatException e1) { - LOGGER.error("Failed to parse expected integer as a double", e); - return null; - } - } - return theInt; - } - - @SuppressWarnings("unused") - private static AdviceExpressionsType generateRequestIdAdvice() { - AdviceExpressionType adviceExpression = new AdviceExpressionType(); - adviceExpression.setAppliesTo(EffectType.PERMIT); - adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_GUARD.stringValue()); - - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_SUBJECT_GUARD_REQUESTID.stringValue()); - designator.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - - AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType(); - assignment.setAttributeId(ToscaDictionary.ID_ADVICE_GUARD_REQUESTID.stringValue()); - assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue()); - assignment.setExpression(new ObjectFactory().createAttributeDesignator(designator)); - - adviceExpression.getAttributeAssignmentExpression().add(assignment); - - AdviceExpressionsType adviceExpressions = new AdviceExpressionsType(); - adviceExpressions.getAdviceExpression().add(adviceExpression); - - return adviceExpressions; - } -} diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java index c75156df..b5585a7c 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -30,6 +30,7 @@ import java.io.IOException; import java.sql.Date; import java.time.Instant; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ServiceLoader; @@ -51,6 +52,8 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.TextFileUtils; 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.ToscaPolicyConversionException; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; @@ -160,6 +163,16 @@ public class CoordinationTest { } /** + * Close the entity manager. + */ + @AfterClass + public static void cleanup() throws Exception { + if (em != null) { + em.close(); + } + } + + /** * Clears the database before each test. * */ @@ -170,52 +183,35 @@ public class CoordinationTest { em.getTransaction().commit(); } - /** - * Check that decision matches expectation. - * - * @param expected from the response - * @param response received - * - **/ - public void checkDecision(String expected, DecisionResponse response) throws CoderException { - LOGGER.info("Looking for {} Decision", expected); - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isNotNull(); - assertThat(response.getStatus()).isEqualTo(expected); - // - // Dump it out as Json - // - LOGGER.info(gson.encode(response)); - } - - /** - * Request a decision and check that it matches expectation. - * - * @param request to send to Xacml PDP - * @param expected from the response - * - **/ - public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException { - // - // Ask for a decision - // - Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); - // - // Check decision - // - checkDecision(expected, decision.getKey()); + @Test + public void test0Basics() throws ToscaPolicyConversionException { + LOGGER.info("**************** Running test0Basics ****************"); + // + // Check the methods in coordination translator that don't get tested by + // the application. + // + CoordinationGuardTranslator translator = new CoordinationGuardTranslator(); + assertThat(translator.convertRequest(null)).isNull(); + assertThat(translator.convertResponse(null)).isNull(); + assertThat(CoordinationGuardTranslator.loadCoordinationDirectiveFromFile( + policyFolder.getRoot().getAbsolutePath() + "/nonexist.yaml")).isNull(); + CoordinationDirective directive = CoordinationGuardTranslator.loadCoordinationDirectiveFromFile( + "src/test/resources/test-directive.yaml"); + assertThat(directive).isNotNull(); } @Test - public void test1() throws CoderException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test1 ****************"); + public void test1Coordination() throws CoderException, IOException, XacmlApplicationException { + LOGGER.info("**************** Running test1Coordination ****************"); // // Now load the test coordination policy - make sure // the pdp can support it and have it load // into the PDP. // - TestUtils.loadPolicies("src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml", - service); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml", service); + assertThat(loadedPolicies).isNotNull(); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.coordination.firstBlocksSecond.test"); // // cl1 doesn't have open action: cl2 should get permit // @@ -266,6 +262,42 @@ public class CoordinationTest { requestAndCheckDecision(requestCl2Node1, DENY); } + /** + * Check that decision matches expectation. + * + * @param expected from the response + * @param response received + * + **/ + public void checkDecision(String expected, DecisionResponse response) throws CoderException { + LOGGER.info("Looking for {} Decision", expected); + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isNotNull(); + assertThat(response.getStatus()).isEqualTo(expected); + // + // Dump it out as Json + // + LOGGER.info(gson.encode(response)); + } + + /** + * Request a decision and check that it matches expectation. + * + * @param request to send to Xacml PDP + * @param expected from the response + * + **/ + public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException { + // + // Ask for a decision + // + Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); + // + // Check decision + // + checkDecision(expected, decision.getKey()); + } + @SuppressWarnings("unchecked") private void insertOperationEvent(DecisionRequest request, String outcome) { // @@ -288,14 +320,4 @@ public class CoordinationTest { em.persist(newEntry); em.getTransaction().commit(); } - - /** - * Close the entity manager. - */ - @AfterClass - public static void cleanup() throws Exception { - if (em != null) { - em.close(); - } - } } diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java index 9c3ae5b2..c62575c0 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -23,6 +23,7 @@ package org.onap.policy.xacml.pdp.application.guard; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import com.att.research.xacml.api.Response; import java.io.File; @@ -30,8 +31,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Date; import java.time.Instant; -import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ServiceLoader; @@ -53,6 +54,7 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.TextFileUtils; 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.ToscaPolicyTypeIdentifier; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; @@ -71,9 +73,7 @@ public class GuardPdpApplicationTest { private static File propertiesFile; private static RestServerParameters clientParams = new RestServerParameters(); private static XacmlApplicationServiceProvider service; - private static DecisionRequest requestVfCount1; - private static DecisionRequest requestVfCount3; - private static DecisionRequest requestVfCount6; + private static DecisionRequest requestVfCount; private static StandardCoder gson = new StandardCoder(); private static EntityManager em; private static final String DENY = "Deny"; @@ -132,17 +132,9 @@ public class GuardPdpApplicationTest { // // Load Decision Requests // - requestVfCount1 = gson.decode( + requestVfCount = gson.decode( TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.1.json"), - DecisionRequest.class); - requestVfCount3 = gson.decode( - TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.3.json"), - DecisionRequest.class); - requestVfCount6 = gson.decode( - TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.6.json"), + "src/test/resources/requests/guard.vfCount.json"), DecisionRequest.class); // // Create EntityManager for manipulating DB @@ -154,7 +146,17 @@ public class GuardPdpApplicationTest { } /** - * Clears the database before each test. + * Close the entity manager. + */ + @AfterClass + public static void cleanup() throws Exception { + if (em != null) { + em.close(); + } + } + + /** + * Clears the database before each test so there are no operations in it. * */ @Before @@ -202,7 +204,7 @@ public class GuardPdpApplicationTest { @Test public void test1Basics() throws CoderException, IOException { - LOGGER.info("**************** Running test1 ****************"); + LOGGER.info("**************** Running test1Basics ****************"); // // Make sure there's an application name // @@ -219,17 +221,17 @@ public class GuardPdpApplicationTest { assertThat(service.supportedPolicyTypes()).isNotEmpty(); assertThat(service.supportedPolicyTypes().size()).isEqualTo(4); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.FrequencyLimiter", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.FrequencyLimiter", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.MinMax", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.MinMax", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.Blacklist", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.Blacklist", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( @@ -239,146 +241,106 @@ public class GuardPdpApplicationTest { @Test public void test2NoPolicies() throws CoderException { - LOGGER.info("**************** Running test2 ****************"); - requestAndCheckDecision(requestVfCount1,PERMIT); + LOGGER.info("**************** Running test2NoPolicies ****************"); + assertThatCode(() -> requestAndCheckDecision(requestVfCount, PERMIT)).doesNotThrowAnyException(); } @Test public void test3FrequencyLimiter() throws CoderException, FileNotFoundException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test3 ****************"); + LOGGER.info("**************** Running test3FrequencyLimiter ****************"); // // Now load the vDNS frequency limiter Policy - make sure // the pdp can support it and have it load // into the PDP. // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml", service); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.frequencylimiter.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.frequency.scaleout"); // // Zero recent actions: should get permit // - requestAndCheckDecision(requestVfCount1,PERMIT); + requestAndCheckDecision(requestVfCount, PERMIT); // // Add entry into operations history DB // - insertOperationEvent(requestVfCount1); - // - // Only one recent actions: should get permit - // - requestAndCheckDecision(requestVfCount1,PERMIT); - // - // Add entry into operations history DB - // - insertOperationEvent(requestVfCount1); + insertOperationEvent(requestVfCount); // // Two recent actions, more than specified limit of 2: should get deny // - requestAndCheckDecision(requestVfCount1,DENY); + requestAndCheckDecision(requestVfCount, DENY); } + @SuppressWarnings("unchecked") @Test public void test4MinMax() throws CoderException, FileNotFoundException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test4 ****************"); + LOGGER.info("**************** Running test4MinMax ****************"); // // Now load the vDNS min max Policy - make sure // the pdp can support it and have it load // into the PDP. // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml", service); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.minmaxvnfs.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.minmax.scaleout"); // - // vfcount=1 below min of 2: should get a Deny + // vfcount=0 below min of 1: should get a Permit // - requestAndCheckDecision(requestVfCount1, DENY); + requestAndCheckDecision(requestVfCount, PERMIT); // - // vfcount=3 between min of 2 and max of 5: should get a Permit + // vfcount=1 between min of 1 and max of 2: should get a Permit // - requestAndCheckDecision(requestVfCount3, PERMIT); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 1); + requestAndCheckDecision(requestVfCount, PERMIT); // - // vfcount=6 above max of 5: should get a Deny + // vfcount=2 hits the max of 2: should get a Deny // - requestAndCheckDecision(requestVfCount6,DENY); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 2); + requestAndCheckDecision(requestVfCount, DENY); // - // Add two entry into operations history DB + // vfcount=3 above max of 2: should get a Deny // - insertOperationEvent(requestVfCount1); - insertOperationEvent(requestVfCount1); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 3); + requestAndCheckDecision(requestVfCount,DENY); // - // vfcount=3 between min of 2 and max of 5, but 2 recent actions is above frequency limit: should get a Deny + // Insert entry into operations history DB - to indicate a successful + // VF Module Create. // - requestAndCheckDecision(requestVfCount3, DENY); + insertOperationEvent(requestVfCount); // - // vfcount=6 above max of 5: should get a Deny + // vfcount=1 between min of 1 and max of 2; MinMax should succeed, + // BUT the frequency limiter should fail // - requestAndCheckDecision(requestVfCount6, DENY); - } - - @Test - public void test5MissingFields() throws FileNotFoundException, IOException, XacmlApplicationException, - CoderException { - LOGGER.info("**************** Running test5 ****************"); - // - // Most likely we would not get a policy with missing fields passed to - // us from the API. But in case that happens, or we decide that some fields - // will be optional due to re-working of how the XACML policies are built, - // let's add support in for that. - // - TestUtils.loadPolicies("src/test/resources/guard.policy-minmax-missing-fields1.yaml", service); - // - // We can create a DecisionRequest on the fly - no need - // to have it in the .json files - // - DecisionRequest request = new DecisionRequest(); - request.setOnapName("JUnit"); - request.setOnapComponent("test5MissingFields"); - request.setRequestId(UUID.randomUUID().toString()); - request.setAction("guard"); - Map<String, Object> guard = new HashMap<>(); - guard.put("actor", "FOO"); - guard.put("recipe", "bar"); - guard.put("vfCount", "4"); - Map<String, Object> resource = new HashMap<>(); - resource.put("guard", guard); - request.setResource(resource); - // - // Ask for a decision - should get permit - // - Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); - LOGGER.info("Looking for Permit Decision {}", decision.getKey()); - assertThat(decision.getKey()).isNotNull(); - assertThat(decision.getKey().getStatus()).isNotNull(); - assertThat(decision.getKey().getStatus()).isEqualTo("Permit"); - // - // Try a deny - // - guard.put("vfCount", "10"); - resource.put("guard", guard); - request.setResource(resource); - decision = service.makeDecision(request, null); - LOGGER.info("Looking for Deny Decision {}", decision.getKey()); - assertThat(decision.getKey()).isNotNull(); - assertThat(decision.getKey().getStatus()).isNotNull(); - assertThat(decision.getKey().getStatus()).isEqualTo("Deny"); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 1); + requestAndCheckDecision(requestVfCount, DENY); } @SuppressWarnings("unchecked") @Test - public void test6Blacklist() throws CoderException, XacmlApplicationException { - LOGGER.info("**************** Running test4 ****************"); + public void test5Blacklist() throws CoderException, XacmlApplicationException { + LOGGER.info("**************** Running test5Blacklist ****************"); // - // Setup requestVfCount1 to point to another target for this test + // Load the blacklist policy in with the others. // - ((Map<String, Object>)requestVfCount3.getResource().get("guard")).put("targets", "vLoadBalancer-01"); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.blacklist.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.blacklist.scaleout"); // - // vfcount=1 above min of 2: should get a permit + // vfcount=0 below min of 1: should get a Permit because target is NOT blacklisted // - requestAndCheckDecision(requestVfCount3, PERMIT); + requestAndCheckDecision(requestVfCount, PERMIT); // - // Now load the vDNS blacklist policy + // vfcount=1 between min of 1 and max of 2: change the // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml", service); + ((Map<String, Object>) requestVfCount.getResource().get("guard")) + .put("target", "the-vfmodule-where-root-is-true"); // - // vfcount=1 above min of 2: should get a permit + // vfcount=0 below min of 1: should get a Deny because target IS blacklisted // - requestAndCheckDecision(requestVfCount3, DENY); + requestAndCheckDecision(requestVfCount, DENY); } @SuppressWarnings("unchecked") @@ -406,14 +368,4 @@ public class GuardPdpApplicationTest { em.getTransaction().commit(); } - /** - * Close the entity manager. - */ - @AfterClass - public static void cleanup() throws Exception { - if (em != null) { - em.close(); - } - } - } diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java new file mode 100644 index 00000000..b3ef3bdd --- /dev/null +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.xacml.pdp.application.guard; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.policy.models.decisions.concepts.DecisionRequest; + +public class GuardPolicyRequestTest { + + @Test + public void testAnomalies() { + DecisionRequest decisionRequest = new DecisionRequest(); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + Map<String, Object> resources = new HashMap<>(); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + resources.put("notguard", "foo"); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + resources.put("guard", null); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + Map<String, Object> guard = new HashMap<>(); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("crap", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("actor", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("recipe", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("clname", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("target", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("vfCount", 1); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + } + +} diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java new file mode 100644 index 00000000..36b43aee --- /dev/null +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java @@ -0,0 +1,319 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.xacml.pdp.application.guard; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.XACML3; +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.StdStatusCode; +import com.att.research.xacml.util.XACMLPolicyWriter; +import java.io.ByteArrayOutputStream; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; +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 org.junit.Test; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.coder.StandardYamlCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.common.utils.resources.TextFileUtils; +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.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GuardTranslatorTest { + private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class); + private static final StandardYamlCoder yamlCoder = new StandardYamlCoder(); + private static StandardCoder gson = new StandardCoder(); + + private GuardTranslator translator = new GuardTranslator(); + + @Test + public void testRequest() throws Exception { + DecisionRequest decisionRequest = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/guard.vfCount.json"), + DecisionRequest.class); + Request xacmlRequest = translator.convertRequest(decisionRequest); + + assertThat(xacmlRequest).isNotNull(); + } + + @Test + public void testResponse() { + StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK); + StdMutableResult result = new StdMutableResult(Decision.PERMIT, status); + StdMutableResponse response = new StdMutableResponse(result); + + DecisionResponse decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString()); + + result = new StdMutableResult(Decision.DENY, status); + response = new StdMutableResponse(result); + decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString()); + + result = new StdMutableResult(Decision.INDETERMINATE, status); + response = new StdMutableResponse(result); + decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString()); + } + + + @Test + public void testBadPolicies() throws Exception { + String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml"); + // + // Serialize it into a class + // + ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class); + // + // Make sure all the fields are setup properly + // + JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); + jtst.fromAuthorative(serviceTemplate); + ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + // + // Get the policies + // + for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { + for (ToscaPolicy policy : policies.values()) { + if ("frequency-missing-properties".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing property limit"); + } else if ("frequency-timewindow".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("timeWindow is not an integer"); + } else if ("minmax-notarget".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing target field in minmax policy"); + } else if ("minmax-nominmax".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing min or max field in minmax policy"); + } else if ("blacklist-noblacklist".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing blacklist"); + } + } + } + } + + @Test + public void testPolicyConversion() throws Exception { + String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml"); + // + // Serialize it into a class + // + ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class); + // + // Make sure all the fields are setup properly + // + JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); + jtst.fromAuthorative(serviceTemplate); + ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + // + // Get the policies + // + for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { + for (ToscaPolicy policy : policies.values()) { + // + // Convert the policy + // + if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy)); + continue; + } + PolicyType xacmlPolicy = translator.convertPolicy(policy); + assertThat(xacmlPolicy).isNotNull(); + // + // Let's dump it out + // + ByteArrayOutputStream os = new ByteArrayOutputStream(); + XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy); + LOGGER.info(os.toString()); + // + // Validate the policy + // + assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName()); + assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion()); + assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull(); + validateCommon(policy, xacmlPolicy); + // + // Validate each policy type + // + if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) { + validateFrequency(policy, xacmlPolicy); + } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) { + validateMinMax(policy, xacmlPolicy); + } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) { + validateBlacklist(policy, xacmlPolicy); + } + } + } + } + + private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundActor = false; + boolean foundOperation = false; + boolean foundTarget = false; + boolean foundControlLoop = false; + boolean foundTimeRange = false; + + assertThat(xacmlPolicy.getTarget()).isNotNull(); + assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty(); + for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + // + // These fields are required + // + if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(match.getAttributeValue().getContent()).isNotNull(); + foundActor = true; + } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(match.getAttributeValue().getContent()).isNotNull(); + foundOperation = true; + } else { + // + // These fields are optional + // + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey("target"); + foundTarget = true; + } + if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP); + foundControlLoop = true; + } + if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE); + foundTimeRange = true; + } + } + } + } + } + assertThat(foundActor && foundOperation).isTrue(); + if (policy.getProperties().containsKey("target")) { + assertThat(foundTarget).isTrue(); + } + if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) { + assertThat(foundControlLoop).isTrue(); + } + if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) { + assertThat(foundTimeRange).isTrue(); + } + } + + private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) { + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + assertThat(((RuleType)rule).getCondition()).isNotNull(); + assertThat(((RuleType)rule).getCondition().getExpression()).isNotNull(); + } + } + + private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundTarget = false; + boolean foundMinOrMax = false; + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + for (AnyOfType anyOf : ((RuleType)rule).getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET); + foundTarget = true; + } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN, + GuardTranslator.FIELD_MAX); + foundMinOrMax = true; + } + } + } + } + } + assertThat(foundTarget && foundMinOrMax).isTrue(); + } + + private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundBlacklist = false; + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + for (AnyOfType anyOf : ((RuleType)rule).getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST); + foundBlacklist = true; + } + } + } + } + } + assertThat(foundBlacklist).isTrue(); + } +} diff --git a/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml b/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml deleted file mode 100644 index 6a441182..00000000 --- a/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml +++ /dev/null @@ -1,19 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.minmax.missing1: - type: onap.policies.controlloop.guard.MinMax - version: 1.0.0 - metadata: - policy-id : guard.minmax.scaleout - policy-version: 1 - properties: - actor: FOO - recipe: bar -# targets: *. -# clname: ControlLoop-Foo-Bar - min: 1 - max: 5 -# guardActiveStart: 00:00:01-05:00 -# guardActiveEnd: 23:59:59-05:00 diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.3.json b/applications/guard/src/test/resources/requests/guard.vfCount.3.json deleted file mode 100644 index 9faa55d6..00000000 --- a/applications/guard/src/test/resources/requests/guard.vfCount.3.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "ONAPName": "Policy", - "ONAPComponent": "drools-pdp", - "ONAPInstance": "usecase-template", - "requestId": "unique-request-id-3", - "action": "guard", - "resource": { - "guard": { - "actor": "SO", - "recipe": "VF Module Create", - "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", - "target": "vLoadBalancer-00", - "vfCount": "3" - } - } -} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.6.json b/applications/guard/src/test/resources/requests/guard.vfCount.6.json deleted file mode 100644 index e00d67ae..00000000 --- a/applications/guard/src/test/resources/requests/guard.vfCount.6.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "ONAPName": "Policy", - "ONAPComponent": "drools-pdp", - "ONAPInstance": "usecase-template", - "requestId": "unique-request-id-2", - "action": "guard", - "resource": { - "guard": { - "actor": "SO", - "recipe": "VF Module Create", - "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", - "target": "vLoadBalancer-00", - "vfCount" : "6" - } - } -} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.1.json b/applications/guard/src/test/resources/requests/guard.vfCount.json index ef1b5f65..7fc7d230 100644 --- a/applications/guard/src/test/resources/requests/guard.vfCount.1.json +++ b/applications/guard/src/test/resources/requests/guard.vfCount.json @@ -9,8 +9,8 @@ "actor": "SO", "recipe": "VF Module Create", "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", - "target": "vLoadBalancer-00", - "vfCount": "1" + "target": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e", + "vfCount": "0" } } } diff --git a/applications/guard/src/test/resources/test-bad-policies.yaml b/applications/guard/src/test/resources/test-bad-policies.yaml new file mode 100644 index 00000000..df2431d4 --- /dev/null +++ b/applications/guard/src/test/resources/test-bad-policies.yaml @@ -0,0 +1,35 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - + frequency-missing-properties: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + - + frequency-timewindow: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + properties: + limit: 5 + timeWindow: i am a bad value + - + minmax-notarget: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: + - + minmax-nominmax: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: + target: foo + - + blacklist-noblacklist: + type: onap.policies.controlloop.guard.common.Blacklist + type_version: 1.0.0 + version: 1.0.0 + properties: diff --git a/applications/guard/src/test/resources/test-directive.yaml b/applications/guard/src/test/resources/test-directive.yaml new file mode 100644 index 00000000..44dfa74b --- /dev/null +++ b/applications/guard/src/test/resources/test-directive.yaml @@ -0,0 +1,4 @@ +controlLoop: + - cl1 + - cl2 +directive: whatisthisvaluesupposedtobe diff --git a/applications/guard/src/test/resources/test-policies.yaml b/applications/guard/src/test/resources/test-policies.yaml new file mode 100644 index 00000000..1ac7271c --- /dev/null +++ b/applications/guard/src/test/resources/test-policies.yaml @@ -0,0 +1,116 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - + frequency-default: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This is the default APPC Restart frequency limiter policy for all control loops. + metadata: + policy-id: frequency-default + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + timeWindow: 10 + timeUnits: minute + limit: 1 + - + frequency-loop-1: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This frequency limiter is for APPC Restart on a specific control loop. It allows more restarts. + metadata: + policy-id: frequency-loop-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + id: loop-1 + timeWindow: 10 + timeUnits: minute + limit: 3 + - + frequency-loop-3: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This frequency limiter is for APPC Restart on a specific control loop. It allows + NO restarts in a time frame. + metadata: + policy-id: frequency-loop-3 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + timeRange: + start_time: T00:00:00Z + end_time: T08:00:00Z + id: loop-3 + timeWindow: 8 + timeUnits: hour + limit: 0 + - + minmax-default: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : minmax-default + policy-version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + target: vf-module-id-1 + min: 1 + max: 5 + - + minmax-vfmodule-loop2: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : minmax-vfmodule-loop2 + policy-version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + id: loop-2 + target: vf-module-id-2 + min: 3 + max: 6 + - + blacklist-1: + type: onap.policies.controlloop.guard.common.Blacklist + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : blacklist-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Migrate + id: loop-5 + blacklist: + - vnf1 + - vnf2 + - + unknown-1: + type: onap.policies.controlloop.guard.common.Unknown + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : unknown-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Migrate + id: loop-5 + blacklist: + - vnf1 + - vnf2
\ No newline at end of file diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml deleted file mode 100644 index 7d3a54ec..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml +++ /dev/null @@ -1,18 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.frequency.scaleout: - type: onap.policies.controlloop.guard.Blacklist - version: 1.0.0 - metadata: - policy-id: guard.frequency.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: vLoadBalancer-01 - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - limit: 2 - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml deleted file mode 100644 index 506a44ed..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml +++ /dev/null @@ -1,20 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.frequency.scaleout: - type: onap.policies.controlloop.guard.FrequencyLimiter - version: 1.0.0 - metadata: - policy-id: guard.frequency.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: .* - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - limit: 2 - timeWindow: 10 - timeUnits: minute - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml deleted file mode 100644 index ff2a423d..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml +++ /dev/null @@ -1,19 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.minmax.scaleout: - type: onap.policies.controlloop.guard.MinMax - version: 1.0.0 - metadata: - policy-id : guard.minmax.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: .* - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - min: 2 - max: 5 - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z diff --git a/xacml-test/pom.xml b/xacml-test/pom.xml index 9127f569..12bd639a 100644 --- a/xacml-test/pom.xml +++ b/xacml-test/pom.xml @@ -32,6 +32,11 @@ <artifactId>xacml-test</artifactId> + <properties> + <!-- There is code to support JUnit testing in this sub-module. --> + <sonar.skip>true</sonar.skip> + </properties> + <dependencies> <dependency> <groupId>org.onap.policy.xacml-pdp.applications</groupId> |