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 com.google.gson.annotations.SerializedName;
36 import java.time.OffsetDateTime;
37 import java.time.OffsetTime;
38 import java.util.Collection;
39 import java.util.List;
42 import lombok.NoArgsConstructor;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
54 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
57 import org.onap.policy.common.parameters.annotations.NotBlank;
58 import org.onap.policy.common.parameters.annotations.NotNull;
59 import org.onap.policy.common.parameters.annotations.Valid;
60 import org.onap.policy.models.decisions.concepts.DecisionRequest;
61 import org.onap.policy.models.decisions.concepts.DecisionResponse;
62 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
63 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
64 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
65 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
66 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
67 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
72 public class GuardTranslator implements ToscaPolicyTranslator {
73 private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslator.class);
76 // common guard property fields
78 public static final String FIELD_ACTOR = "actor";
79 public static final String FIELD_OPERATION = "operation";
80 public static final String FIELD_CONTROLLOOP = "id";
81 public static final String FIELD_TIMERANGE = "timeRange";
84 // frequency property fields
86 public static final String FIELD_TIMEWINDOW = "timeWindow";
87 public static final String FIELD_TIMEUNITS = "timeUnits";
88 public static final String FIELD_LIMIT = "limit";
91 // minmax property fields
93 public static final String FIELD_TARGET = "target";
94 public static final String FIELD_MIN = "min";
95 public static final String FIELD_MAX = "max";
98 // blacklist property fields
100 public static final String FIELD_BLACKLIST = "blacklist";
103 // filter property fields
105 public static final String FIELD_FILTER_WHITELIST = "whitelist";
106 public static final String FIELD_FILTER_ALGORITHM = "algorithm";
107 public static final String FIELD_FILTER_FILTERS = "filters";
108 public static final String FIELD_FILTER_FIELD = "field";
109 public static final String FIELD_FILTER_FUNCTION = "function";
110 public static final String FIELD_FILTER_FILTER = "filter";
111 public static final String FIELD_FILTER_BLACKLIST = "blacklist";
113 public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter";
114 public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax";
115 public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist";
116 public static final String POLICYTYPE_FILTER = "onap.policies.controlloop.guard.common.Filter";
119 // Variable definitions
121 private static final String VARIABLE_TIMEINRANGE = "timeInRange";
125 * Convert the policy.
128 public Object convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
130 // Policy name should be at the root
132 String policyName = toscaPolicy.getMetadata().get("policy-id");
134 // Set it as the policy ID
136 var newPolicyType = new PolicyType();
137 newPolicyType.setPolicyId(policyName);
139 // Optional description
141 newPolicyType.setDescription(toscaPolicy.getDescription());
143 // There should be a metadata section
145 this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata());
147 // There should be properties metadata section
149 if (toscaPolicy.getProperties() == null) {
150 throw new ToscaPolicyConversionException("no properties specified on guard policy: " + policyName);
153 // Generate the TargetType - add true if not blacklist
155 newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(),
156 ! POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())));
158 // Add specific's per guard policy type
160 if (POLICYTYPE_FREQUENCY.equals(toscaPolicy.getType())) {
161 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
162 generateFrequencyRules(toscaPolicy, policyName, newPolicyType);
163 } else if (POLICYTYPE_MINMAX.equals(toscaPolicy.getType())) {
164 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
165 generateMinMaxRules(toscaPolicy, policyName, newPolicyType);
166 } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) {
167 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
168 generateBlacklistRules(toscaPolicy, policyName, newPolicyType);
169 } else if (POLICYTYPE_FILTER.equals(toscaPolicy.getType())) {
170 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
171 generateFilterRules(toscaPolicy, policyName, newPolicyType);
173 throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType());
176 // Add in our variable definition
178 VariableReferenceType variable = this.createTimeRangeVariable(toscaPolicy.getProperties(), newPolicyType);
179 if (variable != null) {
181 // Update all the rules to have conditions for this variable
183 this.addVariableToConditionTypes(variable, newPolicyType);
185 return newPolicyType;
189 * This method iterates through all the existing rules, adding in a conditionType that will test
190 * whether the Variable is true or false. Any existing ConditionType will be updated to AND with the
193 * @param variable VariableDefinitionType to add
194 * @param newPolicyType PolicyType that will be updated
196 protected void addVariableToConditionTypes(VariableReferenceType variable,
197 PolicyType newPolicyType) {
199 // Iterate through the rules
201 for (Object objectType : newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
202 if (objectType instanceof RuleType) {
203 RuleType rule = (RuleType) objectType;
204 if (rule.getCondition() == null) {
206 // No condition already, just create and add a new one
208 var condition = new ConditionType();
209 condition.setExpression(new ObjectFactory().createVariableReference(variable));
210 rule.setCondition(condition);
213 // Need to create a new ConditionType that treats all the expressions as an AND
214 // with the Variable.
216 rule.setCondition(ToscaPolicyTranslatorUtils.addVariableToCondition(rule.getCondition(), variable,
217 XACML3.ID_FUNCTION_AND));
227 public Request convertRequest(DecisionRequest request) throws ToscaPolicyConversionException {
228 LOGGER.info("Converting Request {}", request);
230 return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request));
231 } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
232 throw new ToscaPolicyConversionException("Failed to convert DecisionRequest", e);
240 public DecisionResponse convertResponse(Response xacmlResponse) {
241 LOGGER.info("Converting Response {}", xacmlResponse);
242 var decisionResponse = new DecisionResponse();
244 // Iterate through all the results
246 for (Result xacmlResult : xacmlResponse.getResults()) {
250 if (xacmlResult.getDecision() == Decision.PERMIT) {
252 // Just simply return a Permit response
254 decisionResponse.setStatus(Decision.PERMIT.toString());
255 } else if (xacmlResult.getDecision() == Decision.DENY) {
257 // Just simply return a Deny response
259 decisionResponse.setStatus(Decision.DENY.toString());
262 // There is no guard policy, so we return a permit
264 decisionResponse.setStatus(Decision.PERMIT.toString());
268 return decisionResponse;
272 * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
274 * @param policy Policy Object to store the metadata
275 * @param map The Metadata TOSCA Map
276 * @return Same Policy Object
278 protected PolicyType fillMetadataSection(PolicyType policy, Map<String, String> map) {
280 // NOTE: The models code ensures the metadata section ALWAYS exists
283 // Add in the Policy Version
285 policy.setVersion(map.get("policy-version"));
290 * Generate the targettype for the policy. Optional to add MatchType for the target. eg. the
291 * blacklist policy type uses the target in a different manner.
293 * @param properties TOSCA properties object
294 * @param addTargets true to go ahead and add target to the match list.
295 * @return TargetType object
296 * @throws ToscaPolicyConversionException if there is a missing property
298 protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets)
299 throws ToscaPolicyConversionException {
301 // Decode the definition from the policy's properties
303 TargetTypeDefinition targetTypeDef =
304 ToscaPolicyTranslatorUtils.decodeProperties(properties, TargetTypeDefinition.class);
306 // Go through potential properties
308 var allOf = new AllOfType();
309 if (targetTypeDef.getActor() != null) {
310 addMatch(allOf, targetTypeDef.getActor(), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
312 if (targetTypeDef.getOperation() != null) {
313 addMatch(allOf, targetTypeDef.getOperation(), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
315 if (addTargets && targetTypeDef.getTarget() != null) {
316 addMatch(allOf, targetTypeDef.getTarget(), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
318 if (targetTypeDef.getId() != null) {
319 addMatch(allOf, targetTypeDef.getId(), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
324 var target = new TargetType();
325 var anyOf = new AnyOfType();
326 anyOf.getAllOf().add(allOf);
327 target.getAnyOf().add(anyOf);
331 @SuppressWarnings("unchecked")
332 protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
333 if (value instanceof String) {
334 if (".*".equals(value.toString())) {
336 // There's no point to even have a match
343 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
344 XACML3.ID_FUNCTION_STRING_EQUAL,
346 XACML3.ID_DATATYPE_STRING,
348 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
350 allOf.getMatch().add(match);
354 if (value instanceof Collection) {
355 ((Collection<String>) value).forEach(val -> {
356 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
357 XACML3.ID_FUNCTION_STRING_EQUAL,
359 XACML3.ID_DATATYPE_STRING,
361 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
363 allOf.getMatch().add(match);
369 protected void addTimeRangeMatch(AllOfType allOf, TimeRange timeRange)
370 throws ToscaPolicyConversionException {
372 var matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
373 XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL,
374 timeRange.getStartTime(),
375 XACML3.ID_DATATYPE_TIME,
376 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
377 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
379 allOf.getMatch().add(matchStart);
381 var matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
382 XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL,
383 timeRange.getEndTime(),
384 XACML3.ID_DATATYPE_TIME,
385 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
386 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
388 allOf.getMatch().add(matchEnd);
391 protected VariableReferenceType createTimeRangeVariable(Map<String, Object> properties, PolicyType newPolicyType)
392 throws ToscaPolicyConversionException {
394 // Decode the definition from the policy's properties
396 TimeRangeDefinition timeRangeDef =
397 ToscaPolicyTranslatorUtils.decodeProperties(properties, TimeRangeDefinition.class);
398 TimeRange timeRange = timeRangeDef.getTimeRange();
399 if (timeRange == null) {
403 // Should also be parseable as an ISO8601 timestamp
405 var startTimeObject = parseTimestamp(timeRange.getStartTime());
406 var endTimeObject = parseTimestamp(timeRange.getEndTime());
408 // They should be the same object types. We cannot establish a range
409 // between an OffsetDateTime and an OffsetTime
411 if (! startTimeObject.getClass().equals(endTimeObject.getClass())) {
412 throw new ToscaPolicyConversionException("start_time and end_time class types do not match");
415 // Create the inner timeInRange ApplyType
417 ApplyType timeInRange = ToscaPolicyTranslatorUtils.generateTimeInRange(timeRange.getStartTime(),
418 timeRange.getEndTime(), true);
419 var variable = new VariableDefinitionType();
420 variable.setVariableId(VARIABLE_TIMEINRANGE);
421 variable.setExpression(new ObjectFactory().createApply(timeInRange));
423 // Add it to the policy
425 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(variable);
427 // Create and return the reference to the variable
429 var reference = new VariableReferenceType();
430 reference.setVariableId(variable.getVariableId());
434 protected Object parseTimestamp(String string) throws ToscaPolicyConversionException {
436 // First see if it is a full datetime object
439 return OffsetDateTime.parse(string);
440 } catch (Exception e) {
441 LOGGER.warn("timestamp {} could not be parsed. This may not be an error.", string, e);
444 // May only be a time object
447 return OffsetTime.parse(string);
448 } catch (Exception e) {
449 throw new ToscaPolicyConversionException("timestamp " + string + " could not be parsed ", e);
453 protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
454 throws ToscaPolicyConversionException {
456 // Decode the definition from the policy's properties
458 FrequencyDefinition frequencyDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
459 FrequencyDefinition.class);
461 // See if its possible to generate a count
463 String timeWindow = null;
464 if (frequencyDef.getTimeWindow() != null) {
465 timeWindow = frequencyDef.getTimeWindow().toString();
470 final ApplyType countCheck =
471 generateCountCheck(frequencyDef.getLimit(), timeWindow, frequencyDef.getTimeUnits());
473 // Create our condition
475 final var condition = new ConditionType();
476 condition.setExpression(new ObjectFactory().createApply(countCheck));
479 // Now we can create our rule
481 var frequencyRule = new RuleType();
482 frequencyRule.setDescription("Frequency limit permit rule");
483 frequencyRule.setRuleId(policyName + ":frequency");
484 frequencyRule.setEffect(EffectType.PERMIT);
485 frequencyRule.setTarget(new TargetType());
489 frequencyRule.setCondition(condition);
491 // Add the rule to the policy
493 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule);
496 protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
497 var designator = new AttributeDesignatorType();
498 designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
499 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
500 designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
502 // Setup issuer - used by the operations PIP to determine
503 // how to do the database query.
505 String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX
506 + CountRecentOperationsPip.ISSUER_NAME
507 + ":tw:" + timeWindow + ":" + timeUnits;
508 designator.setIssuer(issuer);
510 var valueLimit = new AttributeValueType();
511 valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
513 // Yes really use toString(), the marshaller will
514 // throw an exception if this is an integer object
517 valueLimit.getContent().add(limit.toString());
519 var factory = new ObjectFactory();
521 var applyOneAndOnly = new ApplyType();
522 applyOneAndOnly.setDescription("Unbag the limit");
523 applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
524 applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
526 var applyLessThan = new ApplyType();
527 applyLessThan.setDescription("return true if current count is less than.");
528 applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue());
529 applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly));
530 applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit));
532 return applyLessThan;
535 protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
536 throws ToscaPolicyConversionException {
538 // Decode the definition from the policy's properties
540 MinMaxDefinition minMaxDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
541 MinMaxDefinition.class);
545 var matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
546 XACML3.ID_FUNCTION_STRING_EQUAL,
547 minMaxDef.getTarget(),
548 XACML3.ID_DATATYPE_STRING,
549 ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
550 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
552 // For the min, if the # of instances is less than the minimum
553 // then allow the scale.
555 if (minMaxDef.getMin() != null) {
556 var matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
557 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
558 minMaxDef.getMin().toString(),
559 XACML3.ID_DATATYPE_INTEGER,
560 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
561 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
563 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
564 generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum"));
566 if (minMaxDef.getMax() != null) {
567 var matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
568 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
569 minMaxDef.getMax().toString(),
570 XACML3.ID_DATATYPE_INTEGER,
571 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
572 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
574 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
575 generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum"));
578 // Do we have at least a min or max?
580 if (minMaxDef.getMin() == null && minMaxDef.getMax() == null) {
581 throw new ToscaPolicyConversionException("Missing min or max field in minmax policy");
585 protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) {
586 var allOf = new AllOfType();
587 allOf.getMatch().add(matchTarget);
588 allOf.getMatch().add(matchMinOrMax);
589 var anyOf = new AnyOfType();
590 anyOf.getAllOf().add(allOf);
591 var target = new TargetType();
592 target.getAnyOf().add(anyOf);
593 var minMaxRule = new RuleType();
594 minMaxRule.setEffect(EffectType.PERMIT);
595 minMaxRule.setDescription(desc);
596 minMaxRule.setRuleId(ruleId);
597 minMaxRule.setTarget(target);
601 protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
602 throws ToscaPolicyConversionException {
604 // Decode the definition from the policy's properties
606 BlacklistDefinition blacklistDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
607 BlacklistDefinition.class);
609 // Iterate the entries and create individual AnyOf so each entry is
612 var target = new TargetType();
613 var anyOf = new AnyOfType();
614 for (Object blacklisted : blacklistDef.blacklist) {
615 var allOf = new AllOfType();
616 this.addMatch(allOf, blacklisted, ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
617 anyOf.getAllOf().add(allOf);
619 target.getAnyOf().add(anyOf);
621 // Create our rule and add the target
623 var blacklistRule = new RuleType();
624 blacklistRule.setEffect(EffectType.DENY);
625 blacklistRule.setDescription("blacklist the entities");
626 blacklistRule.setRuleId(policyName + ":blacklist");
627 blacklistRule.setTarget(target);
629 // Add the rule to the policy
631 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule);
634 protected void generateFilterRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
635 throws ToscaPolicyConversionException {
637 // Decode the definition from the policy's properties
639 FilterDefinition filterDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
640 FilterDefinition.class);
642 // Set the combining algorithm
644 switch (filterDef.getAlgorithm()) {
645 case "whitelist-overrides":
646 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_OVERRIDES.stringValue());
648 case "blacklist-overrides":
649 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_OVERRIDES.stringValue());
652 throw new ToscaPolicyConversionException(
653 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
656 // Iterate the filters
659 for (FilterAttribute filterAttributes : filterDef.filters) {
661 // Check fields requiring extra validation
663 String field = validateFilterPropertyField(filterAttributes.getField());
664 Identifier function = validateFilterPropertyFunction(filterAttributes.getFunction());
666 // Create our filter rule
668 RuleType filterRule = createFilterRule(policyName + ":rule" + ruleId++, field, filterAttributes.getFilter(),
669 function, filterAttributes.getBlacklist());
671 // Add the rule to the policy
673 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(filterRule);
677 protected String validateFilterPropertyField(String field)
678 throws ToscaPolicyConversionException {
679 String fieldLowerCase = field.toLowerCase();
680 switch (fieldLowerCase) {
681 case "generic-vnf.vnf-name":
682 case "generic-vnf.vnf-id":
683 case "generic-vnf.vnf-type":
684 case "generic-vnf.nf-naming-code":
685 case "vserver.vserver-id":
686 case "cloud-region.cloud-region-id":
687 return fieldLowerCase;
689 throw new ToscaPolicyConversionException("Unexpected value for field in filter");
693 protected Identifier validateFilterPropertyFunction(String function)
694 throws ToscaPolicyConversionException {
695 switch (function.toLowerCase()) {
697 return XACML3.ID_FUNCTION_STRING_EQUAL;
698 case "string-equal-ignore-case":
699 return XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE;
700 case "string-regexp-match":
701 return XACML3.ID_FUNCTION_STRING_REGEXP_MATCH;
702 case "string-contains":
703 return XACML3.ID_FUNCTION_STRING_CONTAINS;
704 case "string-greater-than":
705 return XACML3.ID_FUNCTION_STRING_GREATER_THAN;
706 case "string-greater-than-or-equal":
707 return XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL;
708 case "string-less-than":
709 return XACML3.ID_FUNCTION_STRING_LESS_THAN;
710 case "string-less-than-or-equal":
711 return XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL;
712 case "string-starts-with":
713 return XACML3.ID_FUNCTION_STRING_STARTS_WITH;
714 case "string-ends-with":
715 return XACML3.ID_FUNCTION_STRING_ENDS_WITH;
717 throw new ToscaPolicyConversionException("Unexpected value for function in filter");
721 protected RuleType createFilterRule(String ruleId, String field, String filter, Identifier function,
722 boolean isBlacklisted) {
723 var rule = new RuleType();
724 rule.setRuleId(ruleId);
729 var matchFilter = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
732 XACML3.ID_DATATYPE_STRING,
733 new IdentifierImpl(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID + field),
734 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE
736 var allOf = new AllOfType();
737 allOf.getMatch().add(matchFilter);
738 var anyOf = new AnyOfType();
739 anyOf.getAllOf().add(allOf);
740 var target = new TargetType();
741 target.getAnyOf().add(anyOf);
743 rule.setTarget(target);
746 rule.setEffect(EffectType.DENY);
748 rule.setEffect(EffectType.PERMIT);
754 public static class TimeRangeDefinition {
755 private @Valid TimeRange timeRange;
759 public static class TargetTypeDefinition {
760 private String actor;
761 private String operation;
762 private String target;
769 public static class TimeRange {
770 @SerializedName("start_time")
771 private String startTime;
773 @SerializedName("end_time")
774 private String endTime;
778 public static class FrequencyDefinition {
780 private Integer limit;
781 private Integer timeWindow;
782 private String timeUnits;
786 public static class MinMaxDefinition {
788 private String target;
795 public static class BlacklistDefinition {
796 private List<@NotNull Object> blacklist;
801 public static class FilterDefinition {
802 private String algorithm;
803 private List<@NotNull @Valid FilterAttribute> filters;
808 public static class FilterAttribute {
809 private String field;
810 private String filter;
811 private String function;
812 private Boolean blacklist;