2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2020 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * SPDX-License-Identifier: Apache-2.0
21 * ============LICENSE_END=========================================================
24 package org.onap.policy.xacml.pdp.application.guard;
26 import com.att.research.xacml.api.DataTypeException;
27 import com.att.research.xacml.api.Decision;
28 import com.att.research.xacml.api.Identifier;
29 import com.att.research.xacml.api.Request;
30 import com.att.research.xacml.api.Response;
31 import com.att.research.xacml.api.Result;
32 import com.att.research.xacml.api.XACML3;
33 import com.att.research.xacml.std.IdentifierImpl;
34 import com.att.research.xacml.std.annotations.RequestParser;
35 import java.time.OffsetDateTime;
36 import java.time.OffsetTime;
37 import java.util.Collection;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
53 import org.apache.commons.lang3.StringUtils;
54 import org.onap.policy.models.decisions.concepts.DecisionRequest;
55 import org.onap.policy.models.decisions.concepts.DecisionResponse;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
57 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
58 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
59 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
60 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
61 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
65 public class GuardTranslator implements ToscaPolicyTranslator {
66 private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslator.class);
69 // common guard property fields
71 public static final String FIELD_ACTOR = "actor";
72 public static final String FIELD_OPERATION = "operation";
73 public static final String FIELD_CONTROLLOOP = "id";
74 public static final String FIELD_TIMERANGE = "timeRange";
77 // frequency property fields
79 public static final String FIELD_TIMEWINDOW = "timeWindow";
80 public static final String FIELD_TIMEUNITS = "timeUnits";
81 public static final String FIELD_LIMIT = "limit";
84 // minmax property fields
86 public static final String FIELD_TARGET = "target";
87 public static final String FIELD_MIN = "min";
88 public static final String FIELD_MAX = "max";
91 // blacklist property fields
93 public static final String FIELD_BLACKLIST = "blacklist";
96 // filter property fields
98 public static final String FIELD_FILTER_WHITELIST = "whitelist";
99 public static final String FIELD_FILTER_ALGORITHM = "algorithm";
100 public static final String FIELD_FILTER_FILTERS = "filters";
101 public static final String FIELD_FILTER_FIELD = "field";
102 public static final String FIELD_FILTER_FUNCTION = "function";
103 public static final String FIELD_FILTER_FILTER = "filter";
104 public static final String FIELD_FILTER_BLACKLIST = "blacklist";
106 public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter";
107 public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax";
108 public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist";
109 public static final String POLICYTYPE_FILTER = "onap.policies.controlloop.guard.common.Filter";
112 // Variable definitions
114 private static final String VARIABLE_TIMEINRANGE = "timeInRange";
116 public GuardTranslator() {
121 * Convert the policy.
124 public Object convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
126 // Policy name should be at the root
128 String policyName = toscaPolicy.getMetadata().get("policy-id");
130 // Set it as the policy ID
132 PolicyType newPolicyType = new PolicyType();
133 newPolicyType.setPolicyId(policyName);
135 // Optional description
137 newPolicyType.setDescription(toscaPolicy.getDescription());
139 // There should be a metadata section
141 this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata());
143 // There should be properties metadata section
145 if (toscaPolicy.getProperties() == null) {
146 throw new ToscaPolicyConversionException("no properties specified on guard policy: " + policyName);
149 // Generate the TargetType - add true if not blacklist
151 newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(),
152 ! POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())));
154 // Add specific's per guard policy type
156 if (POLICYTYPE_FREQUENCY.equals(toscaPolicy.getType())) {
157 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
158 generateFrequencyRules(toscaPolicy, policyName, newPolicyType);
159 } else if (POLICYTYPE_MINMAX.equals(toscaPolicy.getType())) {
160 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
161 generateMinMaxRules(toscaPolicy, policyName, newPolicyType);
162 } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) {
163 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
164 generateBlacklistRules(toscaPolicy, policyName, newPolicyType);
165 } else if (POLICYTYPE_FILTER.equals(toscaPolicy.getType())) {
166 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
167 generateFilterRules(toscaPolicy, policyName, newPolicyType);
169 throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType());
172 // Add in our variable definition
174 Object timeRange = toscaPolicy.getProperties().get(FIELD_TIMERANGE);
175 if (timeRange != null) {
176 VariableReferenceType variable = this.createTimeRangeVariable(timeRange, newPolicyType);
178 // Update all the rules to have conditions for this variable
180 this.addVariableToConditionTypes(variable, newPolicyType);
182 return newPolicyType;
186 * This method iterates through all the existing rules, adding in a conditionType that will test
187 * whether the Variable is true or false. Any existing ConditionType will be updated to AND with the
190 * @param variable VariableDefinitionType to add
191 * @param newPolicyType PolicyType that will be updated
193 private void addVariableToConditionTypes(VariableReferenceType variable,
194 PolicyType newPolicyType) {
196 // Iterate through the rules
198 for (Object objectType : newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
199 if (objectType instanceof RuleType) {
200 RuleType rule = (RuleType) objectType;
201 if (rule.getCondition() == null) {
203 // No condition already, just create and add a new one
205 ConditionType condition = new ConditionType();
206 condition.setExpression(new ObjectFactory().createVariableReference(variable));
207 rule.setCondition(condition);
210 // Need to create a new ConditionType that treats all the expressions as an AND
211 // with the Variable.
213 rule.setCondition(ToscaPolicyTranslatorUtils.addVariableToCondition(rule.getCondition(), variable,
214 XACML3.ID_FUNCTION_AND));
224 public Request convertRequest(DecisionRequest request) throws ToscaPolicyConversionException {
225 LOGGER.info("Converting Request {}", request);
227 return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request));
228 } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
229 throw new ToscaPolicyConversionException("Failed to convert DecisionRequest", e);
237 public DecisionResponse convertResponse(Response xacmlResponse) {
238 LOGGER.info("Converting Response {}", xacmlResponse);
239 DecisionResponse decisionResponse = new DecisionResponse();
241 // Iterate through all the results
243 for (Result xacmlResult : xacmlResponse.getResults()) {
247 if (xacmlResult.getDecision() == Decision.PERMIT) {
249 // Just simply return a Permit response
251 decisionResponse.setStatus(Decision.PERMIT.toString());
252 } else if (xacmlResult.getDecision() == Decision.DENY) {
254 // Just simply return a Deny response
256 decisionResponse.setStatus(Decision.DENY.toString());
259 // There is no guard policy, so we return a permit
261 decisionResponse.setStatus(Decision.PERMIT.toString());
265 return decisionResponse;
269 * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
271 * @param policy Policy Object to store the metadata
272 * @param map The Metadata TOSCA Map
273 * @return Same Policy Object
275 protected PolicyType fillMetadataSection(PolicyType policy, Map<String, String> map) {
277 // NOTE: The models code ensures the metadata section ALWAYS exists
280 // Add in the Policy Version
282 policy.setVersion(map.get("policy-version"));
287 * Generate the targettype for the policy. Optional to add MatchType for the target. eg. the
288 * blacklist policy type uses the target in a different manner.
290 * @param properties TOSCA properties object
291 * @param addTargets true to go ahead and add target to the match list.
292 * @return TargetType object
293 * @throws ToscaPolicyConversionException if there is a missing property
295 protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets)
296 throws ToscaPolicyConversionException {
298 // Go through potential properties
300 AllOfType allOf = new AllOfType();
301 if (properties.containsKey(FIELD_ACTOR)) {
302 addMatch(allOf, properties.get(FIELD_ACTOR), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
304 if (properties.containsKey(FIELD_OPERATION)) {
305 addMatch(allOf, properties.get(FIELD_OPERATION), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
307 if (addTargets && properties.containsKey(FIELD_TARGET)) {
308 addMatch(allOf, properties.get(FIELD_TARGET), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
310 if (properties.containsKey(FIELD_CONTROLLOOP)) {
311 addMatch(allOf, properties.get(FIELD_CONTROLLOOP), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
316 TargetType target = new TargetType();
317 AnyOfType anyOf = new AnyOfType();
318 anyOf.getAllOf().add(allOf);
319 target.getAnyOf().add(anyOf);
323 @SuppressWarnings("unchecked")
324 protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
325 if (value instanceof String) {
326 if (".*".equals(value.toString())) {
328 // There's no point to even have a match
335 MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
336 XACML3.ID_FUNCTION_STRING_EQUAL,
338 XACML3.ID_DATATYPE_STRING,
340 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
342 allOf.getMatch().add(match);
346 if (value instanceof Collection) {
347 ((Collection<String>) value).forEach(val -> {
348 MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
349 XACML3.ID_FUNCTION_STRING_EQUAL,
351 XACML3.ID_DATATYPE_STRING,
353 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
355 allOf.getMatch().add(match);
361 @SuppressWarnings("rawtypes")
362 protected void addTimeRangeMatch(AllOfType allOf, Object timeRange)
363 throws ToscaPolicyConversionException {
364 if (! (timeRange instanceof Map)) {
365 throw new ToscaPolicyConversionException("timeRange is not a map object " + timeRange.getClass());
368 MatchType matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
369 XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL,
370 ((Map) timeRange).get("start_time").toString(),
371 XACML3.ID_DATATYPE_TIME,
372 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
373 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
375 allOf.getMatch().add(matchStart);
377 MatchType matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
378 XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL,
379 ((Map) timeRange).get("end_time").toString(),
380 XACML3.ID_DATATYPE_TIME,
381 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
382 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
384 allOf.getMatch().add(matchEnd);
387 @SuppressWarnings("rawtypes")
388 protected VariableReferenceType createTimeRangeVariable(Object timeRange, PolicyType newPolicyType)
389 throws ToscaPolicyConversionException {
391 // Sanity check the properties
393 if (! (timeRange instanceof Map)) {
394 throw new ToscaPolicyConversionException("timeRange is not a map object " + timeRange.getClass());
396 String startTimestamp;
399 startTimestamp = ((Map) timeRange).get("start_time").toString();
400 endTimestamp = ((Map) timeRange).get("end_time").toString();
401 if (StringUtils.isBlank(startTimestamp)) {
402 throw new ToscaPolicyConversionException("Missing timeRange start_time property");
404 if (StringUtils.isBlank(endTimestamp)) {
405 throw new ToscaPolicyConversionException("Missing timeRange end_time property");
407 } catch (ToscaPolicyConversionException e) {
409 } catch (Exception e) {
410 throw new ToscaPolicyConversionException("Invalid timeRange", e);
413 // Should also be parseable as an ISO8601 timestamp
415 Object startTimeObject = parseTimestamp(startTimestamp);
416 Object endTimeObject = parseTimestamp(endTimestamp);
418 // They should be the same object types. We cannot establish a range
419 // between an OffsetDateTime and an OffsetTime
421 if (! startTimeObject.getClass().equals(endTimeObject.getClass())) {
422 throw new ToscaPolicyConversionException("start_time and end_time class types do not match");
425 // Create the inner timeInRange ApplyType
427 ApplyType timeInRange = ToscaPolicyTranslatorUtils.generateTimeInRange(startTimestamp, endTimestamp, true);
428 VariableDefinitionType variable = new VariableDefinitionType();
429 variable.setVariableId(VARIABLE_TIMEINRANGE);
430 variable.setExpression(new ObjectFactory().createApply(timeInRange));
432 // Add it to the policy
434 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(variable);
436 // Create and return the reference to the variable
438 VariableReferenceType reference = new VariableReferenceType();
439 reference.setVariableId(variable.getVariableId());
443 private Object parseTimestamp(String string) throws ToscaPolicyConversionException {
445 // First see if it is a full datetime object
448 return OffsetDateTime.parse(string);
449 } catch (Exception e) {
450 LOGGER.warn("timestamp {} could not be parsed. This may not be an error.", string, e);
453 // May only be a time object
456 return OffsetTime.parse(string);
457 } catch (Exception e) {
458 throw new ToscaPolicyConversionException("timestamp " + string + " could not be parsed ", e);
462 protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
463 throws ToscaPolicyConversionException {
465 // We must have the limit
467 if (! toscaPolicy.getProperties().containsKey(FIELD_LIMIT)) {
468 throw new ToscaPolicyConversionException("Missing property limit");
471 // See if its possible to generate a count
473 Integer limit = ToscaPolicyTranslatorUtils.parseInteger(
474 toscaPolicy.getProperties().get(FIELD_LIMIT).toString());
476 throw new ToscaPolicyConversionException("Missing limit value");
478 String timeWindow = null;
479 if (toscaPolicy.getProperties().containsKey(FIELD_TIMEWINDOW)) {
480 Integer intTimeWindow = ToscaPolicyTranslatorUtils.parseInteger(
481 toscaPolicy.getProperties().get(FIELD_TIMEWINDOW).toString());
482 if (intTimeWindow == null) {
483 throw new ToscaPolicyConversionException("timeWindow is not an integer");
485 timeWindow = intTimeWindow.toString();
487 String timeUnits = null;
488 if (toscaPolicy.getProperties().containsKey(FIELD_TIMEUNITS)) {
489 timeUnits = toscaPolicy.getProperties().get(FIELD_TIMEUNITS).toString();
494 final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits);
496 // Create our condition
498 final ConditionType condition = new ConditionType();
499 condition.setExpression(new ObjectFactory().createApply(countCheck));
502 // Now we can create our rule
504 RuleType frequencyRule = new RuleType();
505 frequencyRule.setDescription("Frequency limit permit rule");
506 frequencyRule.setRuleId(policyName + ":frequency");
507 frequencyRule.setEffect(EffectType.PERMIT);
508 frequencyRule.setTarget(new TargetType());
512 frequencyRule.setCondition(condition);
514 // Add the rule to the policy
516 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule);
519 protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
520 AttributeDesignatorType designator = new AttributeDesignatorType();
521 designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
522 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
523 designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
525 // Setup issuer - used by the operations PIP to determine
526 // how to do the database query.
528 String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX
529 + CountRecentOperationsPip.ISSUER_NAME
530 + ":tw:" + timeWindow + ":" + timeUnits;
531 designator.setIssuer(issuer);
533 AttributeValueType valueLimit = new AttributeValueType();
534 valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
536 // Yes really use toString(), the marshaller will
537 // throw an exception if this is an integer object
540 valueLimit.getContent().add(limit.toString());
542 ObjectFactory factory = new ObjectFactory();
544 ApplyType applyOneAndOnly = new ApplyType();
545 applyOneAndOnly.setDescription("Unbag the limit");
546 applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
547 applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
549 ApplyType applyLessThan = new ApplyType();
550 applyLessThan.setDescription("return true if current count is less than.");
551 applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue());
552 applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly));
553 applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit));
555 return applyLessThan;
558 protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
559 throws ToscaPolicyConversionException {
563 if (! toscaPolicy.getProperties().containsKey(FIELD_TARGET)) {
564 throw new ToscaPolicyConversionException("Missing target field in minmax policy");
566 MatchType matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
567 XACML3.ID_FUNCTION_STRING_EQUAL,
568 toscaPolicy.getProperties().get(FIELD_TARGET).toString(),
569 XACML3.ID_DATATYPE_STRING,
570 ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
571 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
573 // For the min, if the # of instances is less than the minimum
574 // then allow the scale.
577 if (toscaPolicy.getProperties().containsKey(FIELD_MIN)) {
578 min = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MIN).toString());
579 MatchType matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
580 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
582 XACML3.ID_DATATYPE_INTEGER,
583 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
584 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
586 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
587 generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum"));
590 if (toscaPolicy.getProperties().containsKey(FIELD_MAX)) {
591 max = ToscaPolicyTranslatorUtils.parseInteger(toscaPolicy.getProperties().get(FIELD_MAX).toString());
592 MatchType matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
593 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
595 XACML3.ID_DATATYPE_INTEGER,
596 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
597 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
599 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
600 generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum"));
603 // Do we have at least a min or max?
605 if (min == null && max == null) {
606 throw new ToscaPolicyConversionException("Missing min or max field in minmax policy");
610 protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) {
611 AllOfType allOf = new AllOfType();
612 allOf.getMatch().add(matchTarget);
613 allOf.getMatch().add(matchMinOrMax);
614 AnyOfType anyOf = new AnyOfType();
615 anyOf.getAllOf().add(allOf);
616 TargetType target = new TargetType();
617 target.getAnyOf().add(anyOf);
618 RuleType minMaxRule = new RuleType();
619 minMaxRule.setEffect(EffectType.PERMIT);
620 minMaxRule.setDescription(desc);
621 minMaxRule.setRuleId(ruleId);
622 minMaxRule.setTarget(target);
626 protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
627 throws ToscaPolicyConversionException {
629 // Validate the blacklist exists
631 if (! toscaPolicy.getProperties().containsKey(FIELD_BLACKLIST)) {
632 throw new ToscaPolicyConversionException("Missing blacklist field");
635 // Get the blacklist, which should be an array or collection.
637 Object arrayBlacklisted = toscaPolicy.getProperties().get(FIELD_BLACKLIST);
638 if (!(arrayBlacklisted instanceof Collection)) {
639 throw new ToscaPolicyConversionException("Blacklist is not a collection");
642 // Iterate the entries and create individual AnyOf so each entry is
645 TargetType target = new TargetType();
646 AnyOfType anyOf = new AnyOfType();
647 for (Object blacklisted : ((Collection<?>) arrayBlacklisted)) {
648 AllOfType allOf = new AllOfType();
649 this.addMatch(allOf, blacklisted, ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
650 anyOf.getAllOf().add(allOf);
652 target.getAnyOf().add(anyOf);
654 // Create our rule and add the target
656 RuleType blacklistRule = new RuleType();
657 blacklistRule.setEffect(EffectType.DENY);
658 blacklistRule.setDescription("blacklist the entities");
659 blacklistRule.setRuleId(policyName + ":blacklist");
660 blacklistRule.setTarget(target);
662 // Add the rule to the policy
664 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule);
667 @SuppressWarnings("unchecked")
668 protected void generateFilterRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
669 throws ToscaPolicyConversionException {
671 // Validate the algorithm
673 if (! toscaPolicy.getProperties().containsKey(FIELD_FILTER_ALGORITHM)) {
674 throw new ToscaPolicyConversionException("Missing algorithm");
676 Object algorithm = toscaPolicy.getProperties().get(FIELD_FILTER_ALGORITHM);
677 if ("whitelist-overrides".equals(algorithm.toString())) {
678 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_OVERRIDES.stringValue());
679 } else if ("blacklist-overrides".equals(algorithm.toString())) {
680 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_OVERRIDES.stringValue());
682 throw new ToscaPolicyConversionException(
683 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
686 // Validate the filters exist and have the right properties
688 if (! toscaPolicy.getProperties().containsKey(FIELD_FILTER_FILTERS)) {
689 throw new ToscaPolicyConversionException("Missing filters");
692 // Get the filters, which should be an array or collection.
694 Object arrayFilters = toscaPolicy.getProperties().get(FIELD_FILTER_FILTERS);
695 if (!(arrayFilters instanceof Collection)) {
696 throw new ToscaPolicyConversionException("Filters is not a collection");
699 // Iterate the filters
702 for (Object filterAttributes : ((Collection<?>) arrayFilters)) {
703 if (!(filterAttributes instanceof Map)) {
704 throw new ToscaPolicyConversionException("Filter should be a map");
707 // All fields must be there
709 String field = validateFilterPropertyField((Map<String, Object>) filterAttributes);
710 String filter = validateFilterPropertyFilter((Map<String, Object>) filterAttributes);
711 Identifier function = validateFilterPropertyFunction((Map<String, Object>) filterAttributes);
712 boolean isBlacklisted = validateFilterPropertyBlacklist((Map<String, Object>) filterAttributes);
714 // Create our filter rule
716 RuleType filterRule = createFilterRule(policyName + ":rule" + ruleId++, field, filter,
717 function, isBlacklisted);
719 // Add the rule to the policy
721 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(filterRule);
725 private String validateFilterPropertyField(Map<String, Object> filterAttributes)
726 throws ToscaPolicyConversionException {
727 Object field = filterAttributes.get(FIELD_FILTER_FIELD);
729 switch (field.toString().toLowerCase()) {
730 case "generic-vnf.vnf-name":
731 case "generic-vnf.vnf-id":
732 case "generic-vnf.vnf-type":
733 case "generic-vnf.nf-naming-code":
734 case "vserver.vserver-id":
735 case "cloud-region.cloud-region-id":
736 return field.toString();
738 throw new ToscaPolicyConversionException("Unexpected value for field in filter");
741 throw new ToscaPolicyConversionException("Missing \'field\' from filter");
744 private String validateFilterPropertyFilter(Map<String, Object> filterAttributes)
745 throws ToscaPolicyConversionException {
746 Object filter = filterAttributes.get(FIELD_FILTER_FILTER);
747 if (filter != null) {
748 return filter.toString();
750 throw new ToscaPolicyConversionException("Missing \'filter\' from filter");
753 private Identifier validateFilterPropertyFunction(Map<String, Object> filterAttributes)
754 throws ToscaPolicyConversionException {
755 Object function = filterAttributes.get(FIELD_FILTER_FUNCTION);
756 if (function != null) {
757 switch (function.toString().toLowerCase()) {
759 return XACML3.ID_FUNCTION_STRING_EQUAL;
760 case "string-equal-ignore-case":
761 return XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE;
762 case "string-regexp-match":
763 return XACML3.ID_FUNCTION_STRING_REGEXP_MATCH;
764 case "string-contains":
765 return XACML3.ID_FUNCTION_STRING_CONTAINS;
766 case "string-greater-than":
767 return XACML3.ID_FUNCTION_STRING_GREATER_THAN;
768 case "string-greater-than-or-equal":
769 return XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL;
770 case "string-less-than":
771 return XACML3.ID_FUNCTION_STRING_LESS_THAN;
772 case "string-less-than-or-equal":
773 return XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL;
774 case "string-starts-with":
775 return XACML3.ID_FUNCTION_STRING_STARTS_WITH;
776 case "string-ends-with":
777 return XACML3.ID_FUNCTION_STRING_ENDS_WITH;
779 throw new ToscaPolicyConversionException("Unexpected value for function in filter");
782 throw new ToscaPolicyConversionException("Missing \'function\' from filter");
785 private boolean validateFilterPropertyBlacklist(Map<String, Object> filterAttributes)
786 throws ToscaPolicyConversionException {
787 Object filter = filterAttributes.get(FIELD_FILTER_BLACKLIST);
788 if (filter != null) {
789 if ("true".equalsIgnoreCase(filter.toString())) {
792 if ("false".equalsIgnoreCase(filter.toString())) {
795 throw new ToscaPolicyConversionException("Unexpected value for blacklist in filter");
797 throw new ToscaPolicyConversionException("Missing \'blacklist\' from filter");
800 private RuleType createFilterRule(String ruleId, String field, String filter, Identifier function,
801 boolean isBlacklisted) {
802 RuleType rule = new RuleType();
803 rule.setRuleId(ruleId);
808 MatchType matchFilter = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
811 XACML3.ID_DATATYPE_STRING,
812 new IdentifierImpl(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID + field),
813 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE
815 AllOfType allOf = new AllOfType();
816 allOf.getMatch().add(matchFilter);
817 AnyOfType anyOf = new AnyOfType();
818 anyOf.getAllOf().add(allOf);
819 TargetType target = new TargetType();
820 target.getAnyOf().add(anyOf);
822 rule.setTarget(target);
825 rule.setEffect(EffectType.DENY);
827 rule.setEffect(EffectType.PERMIT);