From a0ad29cdb6d6f541aac59f9e265f79d3ad085560 Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Sun, 8 Mar 2020 10:41:26 -0400 Subject: Updates to support fixed guard policy types Because the new TOSCA compliant policy types support required fields, we can simplify the guard translator to utilize Match in the target vs the previous complicated Condition usage. Added test coverage to bump above 90% specifically for the guard and coordination code. Added a sonar exclusion for the test module. Issue-ID: POLICY-2244 Change-Id: Ia90d117bd7b86d28a2268fd5ab8315dce7bf0c12 Signed-off-by: Pamela Dragosh --- .../pdp/application/guard/GuardPdpApplication.java | 15 +- .../pdp/application/guard/GuardPolicyRequest.java | 146 ++++ .../pdp/application/guard/GuardTranslator.java | 505 +++++++++++++ .../guard/LegacyGuardPolicyRequest.java | 155 ---- .../application/guard/LegacyGuardTranslator.java | 786 --------------------- 5 files changed, 658 insertions(+), 949 deletions(-) create mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java create mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java delete mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java delete mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java (limited to 'applications/guard/src/main') diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java index 0073f74e..b4e431c4 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,23 +42,22 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplication.class); private static final String STRING_VERSION100 = "1.0.0"; private List supportedPolicyTypes = new ArrayList<>(); - private LegacyGuardTranslator legacyTranslator = new LegacyGuardTranslator(); + private GuardTranslator guardTranslator = new GuardTranslator(); private CoordinationGuardTranslator coordinationTranslator = new CoordinationGuardTranslator(); - /** * Constructor. * */ public GuardPdpApplication() { this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", + GuardTranslator.POLICYTYPE_FREQUENCY, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", + GuardTranslator.POLICYTYPE_MINMAX, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", + GuardTranslator.POLICYTYPE_BLACKLIST, STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", @@ -101,8 +100,8 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { LOGGER.debug("returning coordinationTranslator"); return coordinationTranslator; } else { - LOGGER.debug("returning legacyTranslator"); - return legacyTranslator; + LOGGER.debug("returning guardTranslator"); + return guardTranslator; } } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java new file mode 100644 index 00000000..51d8f0ed --- /dev/null +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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 GuardPolicyRequest { + + 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; + + public GuardPolicyRequest() { + super(); + } + + /** + * Parses the DecisionRequest into a StdMetadataPolicyRequest. + * + * @param decisionRequest Input DecisionRequest + * @return StdMetadataPolicyRequest + */ + @SuppressWarnings("unchecked") + public static GuardPolicyRequest createInstance(DecisionRequest decisionRequest) { + // + // Create our return object + // + GuardPolicyRequest request = new GuardPolicyRequest(); + // + // 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 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 guard = (Map) 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("target")) { + request.targetId = guard.get("target").toString(); + } + if (guard.containsKey("vfCount")) { + // + // TODO this can potentially throw a NumberFormatException. Fix this to + // throw the exception when you fix the ConvertRequest to throw exceptions also. + // + request.vfCount = Integer.decode(guard.get("vfCount").toString()); + } + + return request; + } + +} diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java new file mode 100644 index 00000000..ebcae8dd --- /dev/null +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java @@ -0,0 +1,505 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.xacml.pdp.application.guard; + +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.annotations.RequestParser; +import java.util.Collection; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; +import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GuardTranslator implements ToscaPolicyTranslator { + private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslator.class); + + // + // common guard property fields + // + public static final String FIELD_ACTOR = "actor"; + public static final String FIELD_OPERATION = "operation"; + public static final String FIELD_CONTROLLOOP = "id"; + public static final String FIELD_TIMERANGE = "timeRange"; + + // + // frequency property fields + // + public static final String FIELD_TIMEWINDOW = "timeWindow"; + public static final String FIELD_TIMEUNITS = "timeUnits"; + public static final String FIELD_LIMIT = "limit"; + + // + // minmax property fields + // + public static final String FIELD_TARGET = "target"; + public static final String FIELD_MIN = "min"; + public static final String FIELD_MAX = "max"; + + // + // blacklist property fields + // + public static final String FIELD_BLACKLIST = "blacklist"; + + public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter"; + public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax"; + public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist"; + + public GuardTranslator() { + super(); + } + + /** + * Convert the policy. + */ + public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + // + // Policy name should be at the root + // + String policyName = toscaPolicy.getMetadata().get("policy-id"); + // + // Set it as the policy ID + // + PolicyType newPolicyType = new PolicyType(); + newPolicyType.setPolicyId(policyName); + // + // Optional description + // + newPolicyType.setDescription(toscaPolicy.getDescription()); + // + // There should be a metadata section + // + this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata()); + // + // Generate the TargetType - add true if not blacklist + // + newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(), + ! POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType()))); + // + // Add specific's per guard policy type + // + if (POLICYTYPE_FREQUENCY.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); + generateFrequencyRules(toscaPolicy, policyName, newPolicyType); + } else if (POLICYTYPE_MINMAX.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); + generateMinMaxRules(toscaPolicy, policyName, newPolicyType); + } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue()); + generateBlacklistRules(toscaPolicy, policyName, newPolicyType); + } else { + throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType()); + } + return newPolicyType; + } + + /** + * Convert Request. + */ + public Request convertRequest(DecisionRequest request) { + LOGGER.info("Converting Request {}", request); + try { + return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request)); + } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) { + LOGGER.error("Failed to convert DecisionRequest: {}", e); + } + // + // TODO throw exception + // + return null; + } + + /** + * Convert response. + */ + public DecisionResponse convertResponse(Response xacmlResponse) { + LOGGER.info("Converting Response {}", xacmlResponse); + DecisionResponse decisionResponse = new DecisionResponse(); + // + // Iterate through all the results + // + for (Result xacmlResult : xacmlResponse.getResults()) { + // + // Check the result + // + if (xacmlResult.getDecision() == Decision.PERMIT) { + // + // Just simply return a Permit response + // + decisionResponse.setStatus(Decision.PERMIT.toString()); + } else if (xacmlResult.getDecision() == Decision.DENY) { + // + // Just simply return a Deny response + // + decisionResponse.setStatus(Decision.DENY.toString()); + } else { + // + // There is no guard policy, so we return a permit + // + decisionResponse.setStatus(Decision.PERMIT.toString()); + } + } + + return decisionResponse; + } + + /** + * From the TOSCA metadata section, pull in values that are needed into the XACML policy. + * + * @param policy Policy Object to store the metadata + * @param map The Metadata TOSCA Map + * @return Same Policy Object + */ + protected PolicyType fillMetadataSection(PolicyType policy, Map map) { + // + // NOTE: The models code ensures the metadata section ALWAYS exists + // + // + // Add in the Policy Version + // + policy.setVersion(map.get("policy-version")); + return policy; + } + + /** + * Generate the targettype for the policy. Optional to add MatchType for the target. eg. the + * blacklist policy type uses the target in a different manner. + * + * @param properties TOSCA properties object + * @param addTargets true to go ahead and add target to the match list. + * @return TargetType object + * @throws ToscaPolicyConversionException if there is a missing property + */ + protected TargetType generateTargetType(Map properties, boolean addTargets) + throws ToscaPolicyConversionException { + // + // Go through potential properties + // + AllOfType allOf = new AllOfType(); + if (properties.containsKey(FIELD_ACTOR)) { + addMatch(allOf, properties.get(FIELD_ACTOR), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR); + } + if (properties.containsKey(FIELD_OPERATION)) { + addMatch(allOf, properties.get(FIELD_OPERATION), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE); + } + if (addTargets && properties.containsKey(FIELD_TARGET)) { + addMatch(allOf, properties.get(FIELD_TARGET), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); + } + if (properties.containsKey(FIELD_CONTROLLOOP)) { + addMatch(allOf, properties.get(FIELD_CONTROLLOOP), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME); + } + if (properties.containsKey(FIELD_TIMERANGE)) { + addTimeRangeMatch(allOf, properties.get(FIELD_TIMERANGE)); + } + // + // Create target + // + TargetType target = new TargetType(); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + target.getAnyOf().add(anyOf); + return target; + } + + @SuppressWarnings("unchecked") + protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) { + if (value instanceof String) { + if (".*".equals(value.toString())) { + // + // There's no point to even have a match + // + return allOf; + } else { + // + // Exact match + // + MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + value, + XACML3.ID_DATATYPE_STRING, + attributeId, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(match); + } + return allOf; + } + if (value instanceof Collection) { + ((Collection) value).forEach(val -> { + MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + val, + XACML3.ID_DATATYPE_STRING, + attributeId, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(match); + }); + } + return allOf; + } + + @SuppressWarnings("rawtypes") + protected void addTimeRangeMatch(AllOfType allOf, Object timeRange) + throws ToscaPolicyConversionException { + if (! (timeRange instanceof Map)) { + throw new ToscaPolicyConversionException("timeRange is not a map object " + timeRange.getClass()); + } + + MatchType matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL, + ((Map) timeRange).get("start_time").toString(), + XACML3.ID_DATATYPE_TIME, + XACML3.ID_ENVIRONMENT_CURRENT_TIME, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + allOf.getMatch().add(matchStart); + + MatchType matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL, + ((Map) timeRange).get("end_time").toString(), + XACML3.ID_DATATYPE_TIME, + XACML3.ID_ENVIRONMENT_CURRENT_TIME, + XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT); + + allOf.getMatch().add(matchEnd); + } + + protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // We must have the limit + // + if (! toscaPolicy.getProperties().containsKey(FIELD_LIMIT)) { + throw new ToscaPolicyConversionException("Missing property limit"); + } + // + // See if its possible to generate a count + // + Integer limit = ToscaPolicyTranslatorUtils.parseInteger( + toscaPolicy.getProperties().get(FIELD_LIMIT).toString()); + if (limit == null) { + throw new ToscaPolicyConversionException("Missing limit value"); + } + String timeWindow = null; + if (toscaPolicy.getProperties().containsKey(FIELD_TIMEWINDOW)) { + Integer intTimeWindow = ToscaPolicyTranslatorUtils.parseInteger( + toscaPolicy.getProperties().get(FIELD_TIMEWINDOW).toString()); + if (intTimeWindow == null) { + throw new ToscaPolicyConversionException("timeWindow is not an integer"); + } + timeWindow = intTimeWindow.toString(); + } + String timeUnits = null; + if (toscaPolicy.getProperties().containsKey(FIELD_TIMEUNITS)) { + timeUnits = toscaPolicy.getProperties().get(FIELD_TIMEUNITS).toString(); + } + // + // Generate a count + // + final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits); + // + // Create our condition + // + final ConditionType condition = new ConditionType(); + condition.setExpression(new ObjectFactory().createApply(countCheck)); + + // + // Now we can create our rule + // + RuleType frequencyRule = new RuleType(); + frequencyRule.setDescription("Frequency limit permit rule"); + frequencyRule.setRuleId(policyName + ":frequency"); + frequencyRule.setEffect(EffectType.PERMIT); + frequencyRule.setTarget(new TargetType()); + // + // Add the condition + // + frequencyRule.setCondition(condition); + // + // Add the rule to the policy + // + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule); + } + + protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) { + AttributeDesignatorType designator = new AttributeDesignatorType(); + designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue()); + designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); + designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); + // + // Setup issuer - used by the operations PIP to determine + // how to do the database query. + // + String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX + + CountRecentOperationsPip.ISSUER_NAME + + ":tw:" + timeWindow + ":" + timeUnits; + designator.setIssuer(issuer); + + AttributeValueType valueLimit = new AttributeValueType(); + valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); + // + // Yes really use toString(), the marshaller will + // throw an exception if this is an integer object + // and not a string. + // + valueLimit.getContent().add(limit.toString()); + + ObjectFactory factory = new ObjectFactory(); + + ApplyType applyOneAndOnly = new ApplyType(); + applyOneAndOnly.setDescription("Unbag the limit"); + applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); + applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); + + ApplyType applyLessThan = new ApplyType(); + applyLessThan.setDescription("return true if current count is less than."); + applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue()); + applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly)); + applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit)); + + return applyLessThan; + } + + protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // Add the target + // + if (! toscaPolicy.getProperties().containsKey(FIELD_TARGET)) { + throw new ToscaPolicyConversionException("Missing target field in minmax policy"); + } + MatchType matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + toscaPolicy.getProperties().get(FIELD_TARGET).toString(), + XACML3.ID_DATATYPE_STRING, + ToscaDictionary.ID_RESOURCE_GUARD_TARGETID, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + // + // For the min, if the # of instances is less than the minimum + // then allow the scale. + // + Integer min = null; + if (toscaPolicy.getProperties().containsKey(FIELD_MIN)) { + min = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MIN).toString()); + MatchType matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_INTEGER_GREATER_THAN, + min.toString(), + XACML3.ID_DATATYPE_INTEGER, + ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add( + generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum")); + } + Integer max = null; + if (toscaPolicy.getProperties().containsKey(FIELD_MAX)) { + max = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MAX).toString()); + MatchType matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_INTEGER_GREATER_THAN, + max.toString(), + XACML3.ID_DATATYPE_INTEGER, + ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add( + generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum")); + } + // + // Do we have at least a min or max? + // + if (min == null && max == null) { + throw new ToscaPolicyConversionException("Missing min or max field in minmax policy"); + } + } + + protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) { + AllOfType allOf = new AllOfType(); + allOf.getMatch().add(matchTarget); + allOf.getMatch().add(matchMinOrMax); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + TargetType target = new TargetType(); + target.getAnyOf().add(anyOf); + RuleType minMaxRule = new RuleType(); + minMaxRule.setEffect(EffectType.PERMIT); + minMaxRule.setDescription(desc); + minMaxRule.setRuleId(ruleId); + minMaxRule.setTarget(target); + return minMaxRule; + } + + protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // Validate the blacklist exists + // + if (! toscaPolicy.getProperties().containsKey(FIELD_BLACKLIST)) { + throw new ToscaPolicyConversionException("Missing blacklist field"); + } + final AllOfType allOf = new AllOfType(); + this.addMatch(allOf, toscaPolicy.getProperties().get(FIELD_BLACKLIST), + ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); + // + // Create our rule and add the target + // + RuleType blacklistRule = new RuleType(); + blacklistRule.setEffect(EffectType.DENY); + blacklistRule.setDescription("blacklist the entities"); + blacklistRule.setRuleId(policyName + ":blacklist"); + TargetType target = new TargetType(); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + target.getAnyOf().add(anyOf); + blacklistRule.setTarget(target); + // + // Add the rule to the policy + // + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule); + } + +} diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java deleted file mode 100644 index bfbe4f64..00000000 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java +++ /dev/null @@ -1,155 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.xacml.pdp.application.guard; - -import com.att.research.xacml.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; - - - 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 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 guard = (Map) 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("target")) { - request.targetId = guard.get("target").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()); - } - - 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 deleted file mode 100644 index 0cb06ea0..00000000 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java +++ /dev/null @@ -1,786 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.xacml.pdp.application.guard; - -import com.att.research.xacml.api.DataTypeException; -import com.att.research.xacml.api.Decision; -import com.att.research.xacml.api.Identifier; -import com.att.research.xacml.api.Request; -import com.att.research.xacml.api.Response; -import com.att.research.xacml.api.Result; -import com.att.research.xacml.api.XACML3; -import com.att.research.xacml.std.annotations.RequestParser; - -import java.util.Collection; -import java.util.Map; - -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; -import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType; - -import org.onap.policy.models.decisions.concepts.DecisionRequest; -import org.onap.policy.models.decisions.concepts.DecisionResponse; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; -import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; -import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; -import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LegacyGuardTranslator implements ToscaPolicyTranslator { - - private static final Logger LOGGER = LoggerFactory.getLogger(LegacyGuardTranslator.class); - - private static final String FIELD_GUARD_ACTIVE_START = "guardActiveStart"; - private static final String FIELD_GUARD_ACTIVE_END = "guardActiveEnd"; - private static final String FIELD_TARGET = "targets"; - private static final String DESC_DEFAULT = "Default is to PERMIT if the policy matches."; - private static final String ID_RULE = ":rule"; - - public LegacyGuardTranslator() { - super(); - } - - @Override - public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { - // - // Policy name should be at the root - // - String policyName = toscaPolicy.getMetadata().get("policy-id"); - // - // Set it as the policy ID - // - PolicyType newPolicyType = new PolicyType(); - newPolicyType.setPolicyId(policyName); - // - // Optional description - // - newPolicyType.setDescription(toscaPolicy.getDescription()); - // - // There should be a metadata section - // - this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata()); - // - // Set the combining rule - // - newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); - // - // Generate the TargetType - add true if not blacklist - // - newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(), - ! "onap.policies.controlloop.guard.Blacklist".equals(toscaPolicy.getType()))); - // - // Now create the Permit Rule - // - RuleType rule = generatePermitRule(policyName, toscaPolicy.getType(), toscaPolicy.getProperties()); - // - // Check if we were able to create the rule - // - if (rule == null) { - LOGGER.error("Failed to create rule"); - return null; - } - // - // Add the rule to the policy - // - newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule); - // - // Return our new policy - // - return newPolicyType; - } - - @Override - public Request convertRequest(DecisionRequest request) { - LOGGER.info("Converting Request {}", request); - try { - return RequestParser.parseRequest(LegacyGuardPolicyRequest.createInstance(request)); - } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) { - LOGGER.error("Failed to convert DecisionRequest: {}", e); - } - // - // TODO throw exception - // - return null; - } - - @Override - public DecisionResponse convertResponse(Response xacmlResponse) { - LOGGER.info("Converting Response {}", xacmlResponse); - DecisionResponse decisionResponse = new DecisionResponse(); - // - // Iterate through all the results - // - for (Result xacmlResult : xacmlResponse.getResults()) { - // - // Check the result - // - if (xacmlResult.getDecision() == Decision.PERMIT) { - // - // Just simply return a Permit response - // - decisionResponse.setStatus(Decision.PERMIT.toString()); - } - if (xacmlResult.getDecision() == Decision.DENY) { - // - // Just simply return a Deny response - // - decisionResponse.setStatus(Decision.DENY.toString()); - } - if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) { - // - // There is no guard policy, so we return a permit - // - decisionResponse.setStatus(Decision.PERMIT.toString()); - } - } - - return decisionResponse; - } - - /** - * From the TOSCA metadata section, pull in values that are needed into the XACML policy. - * - * @param policy Policy Object to store the metadata - * @param map The Metadata TOSCA Map - * @return Same Policy Object - * @throws ToscaPolicyConversionException If there is something missing from the metadata - */ - protected PolicyType fillMetadataSection(PolicyType policy, - Map map) throws ToscaPolicyConversionException { - if (! map.containsKey("policy-id")) { - throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-id"); - } else { - // - // Do nothing here - the XACML PolicyId is used from TOSCA Policy Name field - // - } - if (! map.containsKey("policy-version")) { - throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version"); - } else { - // - // Add in the Policy Version - // - policy.setVersion(map.get("policy-version")); - } - return policy; - } - - protected TargetType generateTargetType(Map properties, boolean addTargets) { - // - // Go through potential properties - // - AllOfType allOf = new AllOfType(); - if (properties.containsKey("actor")) { - addMatch(allOf, properties.get("actor"), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR); - } - if (properties.containsKey("recipe")) { - addMatch(allOf, properties.get("recipe"), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE); - } - if (addTargets && properties.containsKey(FIELD_TARGET)) { - addMatch(allOf, properties.get(FIELD_TARGET), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID); - } - if (properties.containsKey("clname")) { - addMatch(allOf, properties.get("clname"), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME); - } - // - // Create target - // - TargetType target = new TargetType(); - AnyOfType anyOf = new AnyOfType(); - anyOf.getAllOf().add(allOf); - target.getAnyOf().add(anyOf); - return target; - } - - private static AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) { - if (value instanceof String) { - if (".*".equals(value.toString())) { - // - // There's no point to even have a match - // - return allOf; - } else { - // - // Exact match - // - MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( - XACML3.ID_FUNCTION_STRING_EQUAL, - value, - XACML3.ID_DATATYPE_STRING, - attributeId, - XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); - - allOf.getMatch().add(match); - } - return allOf; - } - if (value instanceof Collection) { - // - // TODO support a collection of that attribute - // - } - return allOf; - } - - private static RuleType generatePermitRule(String policyName, String policyType, Map properties) - throws ToscaPolicyConversionException { - // - // Now determine which policy type we are generating - // - if ("onap.policies.controlloop.guard.FrequencyLimiter".equals(policyType)) { - return generateFrequencyPermit(policyName, properties); - } else if ("onap.policies.controlloop.guard.MinMax".equals(policyType)) { - return generateMinMaxPermit(policyName, properties); - } else if ("onap.policies.controlloop.guard.Blacklist".equals(policyType)) { - return generateBlacklistPermit(policyName, properties); - } - LOGGER.error("Missing policy type in the policy"); - return null; - } - - private static RuleType generateFrequencyPermit(String policyName, Map properties) - throws ToscaPolicyConversionException { - // - // See if its possible to generate a count - // - Integer limit = parseInteger(properties.get("limit").toString()); - if (limit == null) { - LOGGER.error("Must have a limit value for frequency guard policy to be created"); - return null; - } - // - // Get the properties that are common among guards - // - String timeWindow = null; - if (properties.containsKey("timeWindow")) { - Integer intTimeWindow = parseInteger(properties.get("timeWindow").toString()); - if (intTimeWindow == null) { - throw new ToscaPolicyConversionException("timeWindow is not an integer"); - } - timeWindow = intTimeWindow.toString(); - } - String timeUnits = null; - if (properties.containsKey("timeUnits")) { - timeUnits = properties.get("timeUnits").toString(); - } - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // Generate a count - // - final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits); - // - // Now combine into an And - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if time range and count checks are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange)); - applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck)); - - // - // Create our condition - // - final ConditionType condition = new ConditionType(); - condition.setExpression(new ObjectFactory().createApply(applyAnd)); - - // - // Now we can create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Add the condition - // - permit.setCondition(condition); - // - // Done - // - return permit; - } - - private static RuleType generateMinMaxPermit(String policyName, Map properties) { - // - // Get the properties that are common among guards - // - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // See if its possible to generate a count - // - Integer min = null; - if (properties.containsKey("min")) { - min = parseInteger(properties.get("min").toString()); - } - Integer max = null; - if (properties.containsKey("max")) { - max = parseInteger(properties.get("max").toString()); - } - final ApplyType minApply = generateMinCheck(min); - final ApplyType maxApply = generateMaxCheck(max); - // - // Make sure we have at least something to check here, - // otherwise there really is no point to this policy. - // - if (timeRange == null && minApply == null && maxApply == null) { - return null; - } - // - // Create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Create the condition - // - permit.setCondition(createCondition(timeRange, minApply, maxApply)); - // - // Done - // - return permit; - } - - private static ConditionType createCondition(ApplyType timeRange, ApplyType minApply, ApplyType maxApply) { - final ConditionType condition = new ConditionType(); - // - // Check if we have all the fields (this can be a little - // ugly) but the ultimate goal is to simplify the policy - // condition to only check for necessary attributes. - // - ObjectFactory factory = new ObjectFactory(); - if (timeRange != null && minApply != null && maxApply != null) { - // - // All 3 must apply - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if all the apply's are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(factory.createApply(timeRange)); - applyAnd.getExpression().add(factory.createApply(minApply)); - applyAnd.getExpression().add(factory.createApply(maxApply)); - // - // Add into the condition - // - condition.setExpression(factory.createApply(applyAnd)); - - return condition; - } - // - // At least one of these applies is null. We need at least - // two to require the And apply. Otherwise there is no need - // for an outer And apply as the single condition can work - // on its own. - // - if (timeRange != null && minApply == null && maxApply == null) { - // - // Only the time range check is necessary - // - condition.setExpression(factory.createApply(timeRange)); - } else if (timeRange == null && minApply != null && maxApply == null) { - // - // Only the min check is necessary - // - condition.setExpression(factory.createApply(minApply)); - } else if (timeRange == null && minApply == null) { - // - // Only the max check is necessary - // - condition.setExpression(factory.createApply(maxApply)); - } else { - // - // Ok we will need an outer And and have at least the - // time range and either min or max check - // - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if all the apply's are true."); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - if (timeRange != null) { - applyAnd.getExpression().add(factory.createApply(timeRange)); - } - if (minApply != null) { - applyAnd.getExpression().add(factory.createApply(minApply)); - } - if (maxApply != null) { - applyAnd.getExpression().add(factory.createApply(maxApply)); - } - // - // Add into the condition - // - condition.setExpression(factory.createApply(applyAnd)); - } - return condition; - } - - private static RuleType generateBlacklistPermit(String policyName, Map properties) { - // - // Generate target - // - if (! properties.containsKey(FIELD_TARGET)) { - LOGGER.error("Missing target for blacklist policy"); - return null; - } - final ApplyType targetApply = generateTargetApply(properties.get(FIELD_TARGET)); - // - // Get the properties that are common among guards - // - String guardActiveStart = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) { - guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString(); - } - String guardActiveEnd = null; - if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) { - guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString(); - } - // - // Generate the time in range - // - final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd); - // - // Create our rule - // - RuleType permit = new RuleType(); - permit.setDescription(DESC_DEFAULT); - permit.setRuleId(policyName + ID_RULE); - permit.setEffect(EffectType.PERMIT); - permit.setTarget(new TargetType()); - // - // Create our condition - // - ObjectFactory factory = new ObjectFactory(); - ApplyType innerApply; - if (timeRange != null) { - ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("Combine the timeRange with target to create AND"); - applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); - applyAnd.getExpression().add(factory.createApply(timeRange)); - applyAnd.getExpression().add(factory.createApply(targetApply)); - // - // Now we need to NOT this so the permit happens - // - ApplyType applyNot = new ApplyType(); - applyNot.setDescription("This should be false for a permit."); - applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue()); - applyNot.getExpression().add(factory.createApply(applyAnd)); - innerApply = applyNot; - } else { - // - // Just the target is needed - // - ApplyType applyNot = new ApplyType(); - applyNot.setDescription("This should be false for a permit."); - applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue()); - applyNot.getExpression().add(factory.createApply(targetApply)); - innerApply = applyNot; - } - // - // Create our condition - // - final ConditionType condition = new ConditionType(); - // - // Add into the condition - // - condition.setExpression(factory.createApply(innerApply)); - // - // Add the condition - // - permit.setCondition(condition); - return permit; - } - - private static ApplyType generateTimeInRange(String start, String end) { - if (start == null || end == null) { - LOGGER.warn("Missing time range start {} end {}", start, end); - return null; - } - if (start.isEmpty() || end.isEmpty()) { - LOGGER.warn("Empty time range start {} end {}", start, end); - return null; - } - - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - - AttributeValueType valueStart = new AttributeValueType(); - valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - valueStart.getContent().add(start); - - AttributeValueType valueEnd = new AttributeValueType(); - valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue()); - valueEnd.getContent().add(end); - - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the current time"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyTimeInRange = new ApplyType(); - applyTimeInRange.setDescription("return true if current time is in range."); - applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue()); - applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly)); - applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart)); - applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd)); - - return applyTimeInRange; - } - - private static ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) { - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Setup issuer - // - String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX - + CountRecentOperationsPip.ISSUER_NAME - + ":tw:" + timeWindow + ":" + timeUnits; - designator.setIssuer(issuer); - - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(limit.toString()); - - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the limit"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyLessThan = new ApplyType(); - applyLessThan.setDescription("return true if current count is less than."); - applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue()); - applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly)); - applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyLessThan; - } - - private static ApplyType generateMinCheck(Integer min) { - if (min == null) { - return null; - } - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // - // - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(min.toString()); - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the min"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyGreaterThanEqual = new ApplyType(); - applyGreaterThanEqual.setDescription("return true if current count is greater than or equal."); - applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue()); - applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyGreaterThanEqual; - } - - private static ApplyType generateMaxCheck(Integer max) { - if (max == null) { - return null; - } - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // - // - AttributeValueType valueLimit = new AttributeValueType(); - valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); - // - // Yes really use toString(), the marshaller will - // throw an exception if this is an integer object - // and not a string. - // - valueLimit.getContent().add(max.toString()); - ObjectFactory factory = new ObjectFactory(); - - ApplyType applyOneAndOnly = new ApplyType(); - applyOneAndOnly.setDescription("Unbag the min"); - applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); - applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - - ApplyType applyLessThanEqual = new ApplyType(); - applyLessThanEqual.setDescription("return true if current count is less than or equal."); - applyLessThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue()); - applyLessThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyLessThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); - - return applyLessThanEqual; - } - - @SuppressWarnings("unchecked") - private static ApplyType generateTargetApply(Object targetObject) { - ObjectFactory factory = new ObjectFactory(); - // - // Create a bag of values - // - ApplyType applyStringBag = new ApplyType(); - applyStringBag.setDescription("Bag the target values"); - applyStringBag.setFunctionId(XACML3.ID_FUNCTION_STRING_BAG.stringValue()); - if (targetObject instanceof Collection) { - for (Object target : ((Collection) targetObject)) { - if (! (target instanceof String)) { - LOGGER.error("Collection of unsupported objects {}", target.getClass()); - return null; - } - AttributeValueType value = new AttributeValueType(); - value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - value.getContent().add(target.toString()); - applyStringBag.getExpression().add(factory.createAttributeValue(value)); - } - } else if (targetObject instanceof String) { - AttributeValueType value = new AttributeValueType(); - value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - value.getContent().add(targetObject.toString()); - applyStringBag.getExpression().add(factory.createAttributeValue(value)); - } else { - LOGGER.warn("Unsupported object for target {}", targetObject.getClass()); - return null; - } - // - // Create our designator - // - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.stringValue()); - designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - // - // Create apply for our AnyOf - // - ApplyType applyAnyOf = new ApplyType(); - applyAnyOf.setDescription("Find designator as anyof the possible values"); - applyAnyOf.setFunctionId(XACML3.ID_FUNCTION_ANY_OF.stringValue()); - applyAnyOf.getExpression().add(factory.createAttributeDesignator(designator)); - applyAnyOf.getExpression().add(factory.createApply(applyStringBag)); - return applyAnyOf; - } - - private static Integer parseInteger(String strInteger) { - Integer theInt = null; - try { - theInt = Integer.parseInt(strInteger); - } catch (NumberFormatException e) { - LOGGER.warn("Expecting an integer", e); - try { - Double dblLimit = Double.parseDouble(strInteger); - theInt = dblLimit.intValue(); - } catch (NumberFormatException e1) { - LOGGER.error("Failed to parse expected integer as a double", e); - return null; - } - } - return theInt; - } - - @SuppressWarnings("unused") - private static AdviceExpressionsType generateRequestIdAdvice() { - AdviceExpressionType adviceExpression = new AdviceExpressionType(); - adviceExpression.setAppliesTo(EffectType.PERMIT); - adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_GUARD.stringValue()); - - AttributeDesignatorType designator = new AttributeDesignatorType(); - designator.setAttributeId(ToscaDictionary.ID_SUBJECT_GUARD_REQUESTID.stringValue()); - designator.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue()); - designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); - - AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType(); - assignment.setAttributeId(ToscaDictionary.ID_ADVICE_GUARD_REQUESTID.stringValue()); - assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue()); - assignment.setExpression(new ObjectFactory().createAttributeDesignator(designator)); - - adviceExpression.getAttributeAssignmentExpression().add(assignment); - - AdviceExpressionsType adviceExpressions = new AdviceExpressionsType(); - adviceExpressions.getAdviceExpression().add(adviceExpression); - - return adviceExpressions; - } -} -- cgit 1.2.3-korg