summaryrefslogtreecommitdiffstats
path: root/applications/guard/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'applications/guard/src/main')
-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
3 files changed, 939 insertions, 4 deletions
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;
+ }
+}