aboutsummaryrefslogtreecommitdiffstats
path: root/applications/guard
diff options
context:
space:
mode:
authorPamela Dragosh <pdragosh@research.att.com>2019-03-22 14:12:52 -0400
committerPamela Dragosh <pdragosh@research.att.com>2019-03-25 13:54:56 -0400
commit2c847e0855b316c162c9fd31456fdf8e338a5dba (patch)
treeceb330604ec28a2cde721ebc0774508a533a1e56 /applications/guard
parentd5c3b36247605392b4f75b2e44296922559baac6 (diff)
Adding optimization application finish guard
Created Optimization application and created a translator for it. The translator makes an assumption that OOF wants to query on policyScope and policyType properties. Rearranged some of the test code for re-usability. Guard policies are now creating for frequency limiter and min max. Probably could use some clean up. Upgraded to xacml 2.0.1 to include a fix for handling null attribute values. Added some code to test missing values. Issue-ID: POLICY-1273 Change-Id: Ia3dbfa992bbe0cbb5aa294c38aa2aff430a3230a Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'applications/guard')
-rw-r--r--applications/guard/pom.xml9
-rw-r--r--applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java40
-rw-r--r--applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java163
-rw-r--r--applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java740
-rw-r--r--applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java354
-rw-r--r--applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml19
-rw-r--r--applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml20
-rw-r--r--applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml19
-rw-r--r--applications/guard/src/test/resources/xacml.properties13
9 files changed, 1244 insertions, 133 deletions
diff --git a/applications/guard/pom.xml b/applications/guard/pom.xml
index 7ee3da08..6696e55e 100644
--- a/applications/guard/pom.xml
+++ b/applications/guard/pom.xml
@@ -34,15 +34,6 @@
<dependencies>
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- </dependency>
- <dependency>
- <groupId>org.onap.policy.common</groupId>
- <artifactId>common-parameters</artifactId>
- <version>${policy.common.version}</version>
- </dependency>
- <dependency>
<groupId>org.onap.policy.xacml-pdp.applications</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
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 18385239..1b12fca8 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
@@ -24,19 +24,23 @@ package org.onap.policy.xacml.pdp.application.guard;
import com.att.research.xacml.api.Request;
import com.att.research.xacml.api.Response;
+import com.att.research.xacml.util.XACMLPolicyWriter;
import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
import org.onap.policy.models.decisions.concepts.DecisionRequest;
import org.onap.policy.models.decisions.concepts.DecisionResponse;
import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
-import org.onap.policy.pdp.xacml.application.common.std.StdMetadataTranslator;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +56,7 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplication.class);
private static final String STRING_VERSION100 = "1.0.0";
private Map<String, String> supportedPolicyTypes = new HashMap<>();
- private StdMetadataTranslator translator = new StdMetadataTranslator();
+ private LegacyGuardTranslator translator = new LegacyGuardTranslator();
/** Constructor.
*
@@ -103,9 +107,37 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider {
throw new ToscaPolicyConversionException("Converted 0 policies");
}
//
- // TODO update properties, save to disk, etc.
+ // Create a copy of the properties object
//
- } catch (ToscaPolicyConversionException e) {
+ Properties newProperties = this.getProperties();
+ //
+ // Iterate through the policies
+ //
+ for (PolicyType newPolicy : listPolicies) {
+ //
+ // Construct the filename
+ //
+ Path refPath = XacmlPolicyUtils.constructUniquePolicyFilename(newPolicy, this.getDataPath());
+ //
+ // Write the policy to disk
+ // Maybe check for an error
+ //
+ XACMLPolicyWriter.writePolicyFile(refPath, newPolicy);
+ //
+ // Add root policy to properties object
+ //
+ XacmlPolicyUtils.addRootPolicy(newProperties, refPath);
+ }
+ //
+ // Write the properties to disk
+ //
+ XacmlPolicyUtils.storeXacmlProperties(newProperties,
+ XacmlPolicyUtils.getPropertiesPath(this.getDataPath()));
+ //
+ // Reload the engine
+ //
+ this.createEngine(newProperties);
+ } catch (IOException | ToscaPolicyConversionException e) {
LOGGER.error("Failed to loadPolicies {}", e);
}
}
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/LegacyGuardPolicyRequest.java
new file mode 100644
index 00000000..0b5b5675
--- /dev/null
+++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java
@@ -0,0 +1,163 @@
+/*-
+ * ============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.std.annotations.XACMLAction;
+import com.att.research.xacml.std.annotations.XACMLRequest;
+import com.att.research.xacml.std.annotations.XACMLResource;
+import com.att.research.xacml.std.annotations.XACMLSubject;
+
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+
+@Getter
+@Setter
+@ToString
+@XACMLRequest(ReturnPolicyIdList = true)
+public class LegacyGuardPolicyRequest {
+
+ private static final String STR_GUARD = "guard";
+
+ @XACMLSubject(includeInResults = true)
+ private String onapName;
+
+ @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:onap-component")
+ private String onapComponent;
+
+ @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:onap-instance")
+ private String onapInstance;
+
+ @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:guard:request:request-id")
+ private String requestId;
+
+ @XACMLAction
+ private String action = STR_GUARD;
+
+ @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:clname:clname-id")
+ private String clnameId;
+
+ @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:actor:actor-id")
+ private String actorId;
+
+ @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:operation:operation-id")
+ private String operationId;
+
+ @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:target-id")
+ private String targetId;
+
+ @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;
+
+ @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:operation:operation-count")
+ private Integer operationCount;
+
+ public LegacyGuardPolicyRequest() {
+ super();
+ }
+
+ /**
+ * Parses the DecisionRequest into a StdMetadataPolicyRequest.
+ *
+ * @param decisionRequest Input DecisionRequest
+ * @return StdMetadataPolicyRequest
+ */
+ @SuppressWarnings("unchecked")
+ public static LegacyGuardPolicyRequest createInstance(DecisionRequest decisionRequest) {
+ //
+ // Create our return object
+ //
+ LegacyGuardPolicyRequest request = new LegacyGuardPolicyRequest();
+ //
+ // Add the subject attributes
+ //
+ request.onapName = decisionRequest.getOnapName();
+ request.onapComponent = decisionRequest.getOnapComponent();
+ request.onapInstance = decisionRequest.getOnapInstance();
+ request.requestId = decisionRequest.getRequestId();
+ //
+ // Now pull from the resources
+ //
+ Map<String, Object> resources = decisionRequest.getResource();
+ //
+ // Just in case nothing is in there
+ //
+ if (resources == null || resources.isEmpty() || ! resources.containsKey(STR_GUARD)) {
+ //
+ // Perhaps we throw an exception and then caller
+ // can put together a response
+ //
+ return request;
+ }
+ Map<String, Object> guard = (Map<String, Object>) resources.get(STR_GUARD);
+ if (guard == null || guard.isEmpty()) {
+ //
+ // again, same problem throw an exception?
+ //
+ return request;
+ }
+ //
+ // Find our fields
+ //
+ if (guard.containsKey("actor")) {
+ request.actorId = guard.get("actor").toString();
+ }
+ if (guard.containsKey("recipe")) {
+ request.operationId = guard.get("recipe").toString();
+ }
+ if (guard.containsKey("clname")) {
+ request.clnameId = guard.get("clname").toString();
+ }
+ if (guard.containsKey("targets")) {
+ request.targetId = guard.get("targets").toString();
+ }
+ if (guard.containsKey("vfCount")) {
+ 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());
+ }
+ //
+ // TODO - remove this when the PIP is hooked up
+ //
+ if (guard.containsKey("operationCount")) {
+ request.operationCount = Integer.decode(guard.get("operationCount").toString());
+ }
+
+ return request;
+ }
+
+}
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
new file mode 100644
index 00000000..81340b4d
--- /dev/null
+++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java
@@ -0,0 +1,740 @@
+/*-
+ * ============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 com.att.research.xacml.util.XACMLPolicyWriter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+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.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.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_POLICIES = "policies";
+ private static final String FIELD_TOPOLOGY_TEMPLATE = "topology_template";
+ private static final String FIELD_GUARD_ACTIVE_START = "guardActiveStart";
+ private static final String FIELD_GUARD_ACTIVE_END = "guardActiveEnd";
+
+ public LegacyGuardTranslator() {
+ super();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<PolicyType> scanAndConvertPolicies(Map<String, Object> toscaObject)
+ throws ToscaPolicyConversionException {
+ //
+ // Our return object
+ //
+ List<PolicyType> scannedPolicies = new ArrayList<>();
+ //
+ // Find the Policies
+ //
+ List<Object> policies;
+
+ if (toscaObject.containsKey(FIELD_POLICIES)) {
+ policies = (List<Object>) toscaObject.get(FIELD_POLICIES);
+ } else if (toscaObject.containsKey(FIELD_TOPOLOGY_TEMPLATE)) {
+ Map<String, Object> topologyTemplate = (Map<String, Object>) toscaObject.get(FIELD_TOPOLOGY_TEMPLATE);
+ if (topologyTemplate.containsKey(FIELD_POLICIES)) {
+ policies = (List<Object>) topologyTemplate.get(FIELD_POLICIES);
+ } else {
+ LOGGER.warn("topologyTemplate does not contain policies");
+ return scannedPolicies;
+ }
+ } else {
+ LOGGER.warn("Failed to find policies or topologyTemplate");
+ return scannedPolicies;
+ }
+ //
+ // Iterate each of the Policies
+ //
+ for (Object policyObject : policies) {
+ //
+ // Get the contents
+ //
+ LOGGER.debug("Found policy {}", policyObject.getClass());
+ Map<String, Object> policyContents = (Map<String, Object>) policyObject;
+ for (Entry<String, Object> entrySet : policyContents.entrySet()) {
+ LOGGER.debug("Entry set {}", entrySet);
+ //
+ // Convert this policy
+ //
+ PolicyType policy = this.convertPolicy(entrySet);
+ if (policy == null) {
+ //
+ // Somehow there wasn't enough information to create
+ // a policy
+ //
+ LOGGER.debug("Failed to convert policy");
+ continue;
+ }
+ //
+ // Debug dump this
+ //
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ XACMLPolicyWriter.writePolicyFile(os, policy);
+ LOGGER.debug("{}", os);
+ } catch (IOException e) {
+ LOGGER.error("Failed to convert {}", e);
+ }
+ //
+ // Convert and add in the new policy
+ //
+ scannedPolicies.add(policy);
+ }
+ }
+
+ return scannedPolicies;
+ }
+
+ @Override
+ public Request convertRequest(DecisionRequest request) {
+ LOGGER.debug("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.debug("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;
+ }
+
+ @SuppressWarnings("unchecked")
+ private PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
+ //
+ // Policy name should be at the root
+ //
+ String policyName = entrySet.getKey();
+ Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
+ //
+ // Set it as the policy ID
+ //
+ PolicyType newPolicyType = new PolicyType();
+ newPolicyType.setPolicyId(policyName);
+ //
+ // Optional description
+ //
+ if (policyDefinition.containsKey("description")) {
+ newPolicyType.setDescription(policyDefinition.get("description").toString());
+ }
+ //
+ // There should be a metadata section
+ //
+ if (! policyDefinition.containsKey("metadata")) {
+ throw new ToscaPolicyConversionException(policyName + " missing metadata section");
+ }
+ this.fillMetadataSection(newPolicyType,
+ (Map<String, Object>) policyDefinition.get("metadata"));
+ //
+ // Set the combining rule
+ //
+ newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
+ //
+ // Generate the TargetType
+ //
+ if (! policyDefinition.containsKey("properties")) {
+ throw new ToscaPolicyConversionException(policyName + " missing properties section");
+ }
+ newPolicyType.setTarget(this.generateTargetType((Map<String, Object>) policyDefinition.get("properties")));
+ //
+ // Now create the Permit Rule
+ //
+ RuleType rule = generatePermitRule(policyName, policyDefinition.get("type").toString(),
+ (Map<String, Object>) policyDefinition.get("properties"));
+ //
+ // Check if we were able to create the rule
+ //
+ if (rule == null) {
+ LOGGER.warn("Failed to create rule");
+ return null;
+ }
+ //
+ // Add the rule to the policy
+ //
+ newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
+ //
+ // Return our new policy
+ //
+ return newPolicyType;
+ }
+
+ /**
+ * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
+ *
+ * @param policy Policy Object to store the metadata
+ * @param metadata 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, Object> metadata) throws ToscaPolicyConversionException {
+ if (! metadata.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 (! metadata.containsKey("policy-version")) {
+ throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version");
+ } else {
+ //
+ // Add in the Policy Version
+ //
+ policy.setVersion(metadata.get("policy-version").toString());
+ }
+ return policy;
+ }
+
+ protected TargetType generateTargetType(Map<String, Object> properties) {
+ //
+ // 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 (properties.containsKey("targets")) {
+ addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
+ }
+ if (properties.containsKey("clname")) {
+ addMatch(allOf, properties.get("clname"), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
+ }
+ if (properties.containsKey("targets")) {
+ addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
+ }
+ //
+ // 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) {
+ //
+ // 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);
+ }
+ return null;
+ }
+
+ private static RuleType generateFrequencyPermit(String policyName, Map<String, Object> properties) {
+ //
+ // See if its possible to generate a count
+ //
+ Integer limit = null;
+ if (properties.containsKey("limit")) {
+ limit = Integer.decode(properties.get("limit").toString());
+ }
+ if (limit == null) {
+ LOGGER.debug("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")) {
+ timeWindow = properties.get("timeWindow").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 all the apply's are true.");
+ applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
+ applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange));
+ applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck));
+ //
+ // And create an outer negation of the And
+ //
+ ApplyType applyNot = new ApplyType();
+ applyNot.setDescription("Negate the and");
+ applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue());
+ applyNot.getExpression().add(new ObjectFactory().createApply(applyAnd));
+
+ //
+ // Create our condition
+ //
+ final ConditionType condition = new ConditionType();
+ condition.setExpression(new ObjectFactory().createApply(applyNot));
+
+ //
+ // Now we can create our rule
+ //
+ RuleType permit = new RuleType();
+ permit.setDescription("Default is to PERMIT if the policy matches.");
+ permit.setRuleId(policyName + ":rule");
+ permit.setEffect(EffectType.PERMIT);
+ permit.setTarget(new TargetType());
+ //
+ // Add the condition
+ //
+ permit.setCondition(condition);
+ //
+ // TODO Add the advice - Is the request id needed to be returned?
+ //
+ // permit.setAdviceExpressions(adviceExpressions);
+ //
+ // 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 = Integer.decode(properties.get("min").toString());
+ }
+ Integer max = null;
+ if (properties.containsKey("max")) {
+ max = Integer.decode(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("Default is to PERMIT if the policy matches.");
+ permit.setRuleId(policyName + ":rule");
+ permit.setEffect(EffectType.PERMIT);
+ permit.setTarget(new TargetType());
+ //
+ // Create our condition
+ //
+ 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));
+ } else {
+ //
+ // 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));
+ }
+ }
+ //
+ // Add the condition
+ //
+ permit.setCondition(condition);
+ //
+ // TODO Add the advice - Is the request id needed to be returned?
+ //
+ // permit.setAdviceExpressions(adviceExpressions);
+ //
+ // Done
+ //
+ 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());
+ //
+ // TODO Add this back in when the operational database PIP is configured.
+ // The issuer indicates that the PIP will be providing this attribute during
+ // the decision making.
+ //
+ // Right now I am faking the count value by re-using the request-id field
+ //
+ //String issuer = "org:onap:xacml:guard:historydb: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 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 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 applyGreaterThanEqual = new ApplyType();
+ applyGreaterThanEqual.setDescription("return true if current count is less than or equal.");
+ applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue());
+ applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
+ applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
+
+ return applyGreaterThanEqual;
+ }
+
+ 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/GuardPdpApplicationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java
index ae4193d3..ff137e13 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
@@ -23,168 +23,300 @@
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.util.XACMLProperties;
-import com.google.common.io.Files;
-import com.google.gson.Gson;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
+import java.util.UUID;
-import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.junit.runners.MethodSorters;
+import org.onap.policy.common.utils.coder.CoderException;
+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.serialization.DecisionRequestMessageBodyHandler;
-import org.onap.policy.models.decisions.serialization.DecisionResponseMessageBodyHandler;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class GuardPdpApplicationTest {
private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplicationTest.class);
private static Properties properties = new Properties();
private static File propertiesFile;
private static XacmlApplicationServiceProvider service;
- private static DecisionRequest requestSinglePolicy;
-
- private static Gson gsonDecisionRequest;
- private static Gson gsonDecisionResponse;
+ private static DecisionRequest requestGuardPermit;
+ private static DecisionRequest requestGuardDeny;
+ private static DecisionRequest requestGuardDeny2;
+ private static StandardCoder gson = new StandardCoder();
@ClassRule
public static final TemporaryFolder policyFolder = new TemporaryFolder();
- @Before
- public void setUp() throws Exception {
+ /**
+ * Copies the xacml.properties and policies files into
+ * temporary folder and loads the service provider saving
+ * instance of provider off for other tests to use.
+ */
+ @BeforeClass
+ public static void setUp() throws Exception {
+ //
+ // Setup our temporary folder
+ //
+ XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
+ propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
+ properties, myCreator);
+ //
+ // Load service
+ //
+ ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
+ ServiceLoader.load(XacmlApplicationServiceProvider.class);
+ //
+ // Find the guard service application and save for use in all the tests
+ //
+ StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
+ Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+ while (iterator.hasNext()) {
+ XacmlApplicationServiceProvider application = iterator.next();
+ //
+ // Is it our service?
+ //
+ if (application instanceof GuardPdpApplication) {
+ //
+ // Should be the first and only one
+ //
+ assertThat(service).isNull();
+ service = application;
+ }
+ strDump.append(application.applicationName());
+ strDump.append(" supports ");
+ strDump.append(application.supportedPolicyTypes());
+ strDump.append(System.lineSeparator());
+ }
+ LOGGER.debug("{}", strDump);
+ //
+ // Tell it to initialize based on the properties file
+ // we just built for it.
+ //
+ service.initialize(propertiesFile.toPath().getParent());
+ }
+ @Test
+ public void test1Basics() throws CoderException, IOException {
+ //
+ // Load Single Decision Request
+ //
+ requestGuardPermit = gson.decode(
+ TextFileUtils.getTextFileAsString(
+ "../../main/src/test/resources/decisions/decision.guard.shouldpermit.input.json"),
+ DecisionRequest.class);
+ //
+ // Load Single Decision Request
+ //
+ requestGuardDeny = gson.decode(TextFileUtils.getTextFileAsString(
+ "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input.json"),
+ DecisionRequest.class);
+ //
+ // Load Single Decision Request
+ //
+ requestGuardDeny2 = gson.decode(TextFileUtils.getTextFileAsString(
+ "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json"),
+ DecisionRequest.class);
+ //
+ // Make sure there's an application name
+ //
+ assertThat(service.applicationName()).isNotEmpty();
+ //
+ // Decisions
+ //
+ assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
+ assertThat(service.actionDecisionsSupported()).contains("guard");
+ //
+ // Ensure it has the supported policy types and
+ // can support the correct policy types.
+ //
+ assertThat(service.supportedPolicyTypes()).isNotEmpty();
+ assertThat(service.supportedPolicyTypes().size()).isEqualTo(2);
+ assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))
+ .isTrue();
+ assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))
+ .isFalse();
+ assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.0")).isTrue();
+ assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.1")).isFalse();
+ assertThat(service.canSupportPolicyType("onap.foo", "1.0.1")).isFalse();
}
@Test
- public void testBasics() {
- assertThatCode(() -> {
+ public void test2NoPolicies() {
+ //
+ // Ask for a decision
+ //
+ DecisionResponse response = service.makeDecision(requestGuardPermit);
+ LOGGER.info("Decision {}", response);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Permit");
+ }
+
+ @Test
+ public void test3FrequencyLimiter() throws CoderException, FileNotFoundException, IOException {
+ //
+ // Now load the vDNS frequency limiter Policy - make sure
+ // the pdp can support it and have it load
+ // into the PDP.
+ //
+ try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml")) {
//
- // Create our Gson builder
+ // Have yaml parse it
//
- gsonDecisionRequest = new DecisionRequestMessageBodyHandler().getGson();
- gsonDecisionResponse = new DecisionResponseMessageBodyHandler().getGson();
+ Yaml yaml = new Yaml();
+ Map<String, Object> toscaObject = yaml.load(is);
//
- // Load Single Decision Request
+ // Load the policies
//
- requestSinglePolicy = gsonDecisionRequest.fromJson(
- TextFileUtils
- .getTextFileAsString("../../main/src/test/resources/decisions/decision.single.input.json"),
- DecisionRequest.class);
+ service.loadPolicies(toscaObject);
//
- // Copy all the properties and root policies to the temporary folder
+ // Ask for a decision - should get permit
//
- try (InputStream is = new FileInputStream("src/test/resources/xacml.properties")) {
- //
- // Load it in
- //
- properties.load(is);
- propertiesFile = policyFolder.newFile("xacml.properties");
- //
- // Copy the root policies
- //
- for (String root : XACMLProperties.getRootPolicyIDs(properties)) {
- //
- // Get a file
- //
- Path rootPath = Paths.get(properties.getProperty(root + ".file"));
- LOGGER.debug("Root file {} {}", rootPath, rootPath.getFileName());
- //
- // Construct new file name
- //
- File newRootPath = policyFolder.newFile(rootPath.getFileName().toString());
- //
- // Copy it
- //
- Files.copy(rootPath.toFile(), newRootPath);
- assertThat(newRootPath).exists();
- //
- // Point to where the new policy is in the temp dir
- //
- properties.setProperty(root + ".file", newRootPath.getAbsolutePath());
- }
- try (OutputStream os = new FileOutputStream(propertiesFile.getAbsolutePath())) {
- properties.store(os, "");
- assertThat(propertiesFile).exists();
- }
- }
+ DecisionResponse response = service.makeDecision(requestGuardPermit);
+ LOGGER.info("Looking for Permit Decision {}", response);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Permit");
//
- // Load service
+ // Dump it out as Json
//
- ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
- ServiceLoader.load(XacmlApplicationServiceProvider.class);
+ LOGGER.info(gson.encode(response));
//
- // Iterate through them - I could store the object as
- // XacmlApplicationServiceProvider pointer.
+ // Ask for a decision - should get deny
//
- // Try this later.
+ response = service.makeDecision(requestGuardDeny2);
+ LOGGER.info("Looking for Deny Decision {}", response);
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Deny");
//
- StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
- Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
- while (iterator.hasNext()) {
- XacmlApplicationServiceProvider application = iterator.next();
- //
- // Is it our service?
- //
- if (application instanceof GuardPdpApplication) {
- //
- // Should be the first and only one
- //
- assertThat(service).isNull();
- service = application;
- }
- strDump.append(application.applicationName());
- strDump.append(" supports ");
- strDump.append(application.supportedPolicyTypes());
- strDump.append(System.lineSeparator());
- }
- LOGGER.debug("{}", strDump);
+ // Dump it out as Json
+ //
+ LOGGER.info(gson.encode(response));
+ }
+ }
+
+ @Test
+ public void test4MinMax() throws CoderException, FileNotFoundException, IOException {
+ //
+ // Now load the vDNS min max Policy - make sure
+ // the pdp can support it and have it load
+ // into the PDP.
+ //
+ try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml")) {
+ //
+ // Have yaml parse it
+ //
+ Yaml yaml = new Yaml();
+ Map<String, Object> toscaObject = yaml.load(is);
+ //
+ // Load the policies
+ //
+ service.loadPolicies(toscaObject);
+ //
+ // Ask for a decision - should get permit
+ //
+ DecisionResponse response = service.makeDecision(requestGuardPermit);
+ LOGGER.info("Looking for Permit Decision {}", response);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Permit");
+ //
+ // Dump it out as Json
+ //
+ LOGGER.info(gson.encode(response));
+ //
+ // Ask for a decision - should get deny
+ //
+ response = service.makeDecision(requestGuardDeny);
+ LOGGER.info("Looking for Deny Decision {}", response);
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Deny");
+ //
+ // Dump it out as Json
+ //
+ LOGGER.info(gson.encode(response));
+ }
+ }
+
+ @Test
+ public void test5MissingFields() throws FileNotFoundException, IOException {
+ LOGGER.debug("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.
+ //
+ try (InputStream is = new FileInputStream("src/test/resources/guard.policy-minmax-missing-fields1.yaml")) {
//
- // Tell it to initialize based on the properties file
- // we just built for it.
+ // Have yaml parse it
//
- service.initialize(propertiesFile.toPath().getParent());
+ Yaml yaml = new Yaml();
+ Map<String, Object> toscaObject = yaml.load(is);
//
- // Make sure there's an application name
+ // Load the policies
//
- assertThat(service.applicationName()).isNotEmpty();
+ service.loadPolicies(toscaObject);
//
- // Decisions
+ // We can create a DecisionRequest on the fly - no need
+ // to have it in the .json files
//
- assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
- assertThat(service.actionDecisionsSupported()).contains("guard");
+ 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);
//
- // Ensure it has the supported policy types and
- // can support the correct policy types.
+ // Ask for a decision - should get permit
//
- assertThat(service.supportedPolicyTypes()).isNotEmpty();
- assertThat(service.supportedPolicyTypes().size()).isEqualTo(2);
- assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))
- .isTrue();
- assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))
- .isFalse();
- assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.0")).isTrue();
- assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.1")).isFalse();
- assertThat(service.canSupportPolicyType("onap.foo", "1.0.1")).isFalse();
+ DecisionResponse response = service.makeDecision(request);
+ LOGGER.info("Looking for Permit Decision {}", response);
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Permit");
//
- // Ensure it supports decisions
+ // Try a deny
//
- assertThat(service.actionDecisionsSupported()).contains("guard");
- }).doesNotThrowAnyException();
+ guard.put("vfCount", "10");
+ resource.put("guard", guard);
+ request.setResource(resource);
+ response = service.makeDecision(request);
+ LOGGER.info("Looking for Deny Decision {}", response);
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isNotNull();
+ assertThat(response.getStatus()).isEqualTo("Deny");
+ }
}
}
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
new file mode 100644
index 00000000..6a441182
--- /dev/null
+++ b/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml
@@ -0,0 +1,19 @@
+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/vDNS.policy.guard.frequency.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml
new file mode 100644
index 00000000..03afd5e2
--- /dev/null
+++ b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml
@@ -0,0 +1,20 @@
+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: scaleOut
+ targets: .*
+ clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3
+ limit: 1
+ timeWindow: 10
+ timeUnits: minute
+ guardActiveStart: 00:00:01-05:00
+ guardActiveEnd: 23:59:59-05:00
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
new file mode 100644
index 00000000..5ac76015
--- /dev/null
+++ b/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml
@@ -0,0 +1,19 @@
+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: scaleOut
+ targets: .*
+ clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3
+ min: 1
+ max: 5
+ guardActiveStart: 00:00:01-05:00
+ guardActiveEnd: 23:59:59-05:00
diff --git a/applications/guard/src/test/resources/xacml.properties b/applications/guard/src/test/resources/xacml.properties
index b32a936c..9bd7bfb8 100644
--- a/applications/guard/src/test/resources/xacml.properties
+++ b/applications/guard/src/test/resources/xacml.properties
@@ -20,18 +20,13 @@ xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctio
xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory
#
-# ONAP Implementation Factories
+# Use a root combining algorithm
#
-#xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapApplicationPolicyFinder
+xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-unless-deny
-#
-# NOTE: If you are testing against a RESTful PDP, then the PDP must be configured with the
-# policies and PIP configuration as defined below. Otherwise, this is the configuration that
-# the embedded PDP uses.
-#
# Policies to load
#
-xacml.rootPolicies=guard
-guard.file=src/main/resources/RootGuardPolicy.xml
+#xacml.rootPolicies=guard
+#guard.file=src/main/resources/RootGuardPolicy.xml