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 oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
54 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
56 import org.onap.policy.common.parameters.annotations.NotBlank;
57 import org.onap.policy.common.parameters.annotations.NotNull;
58 import org.onap.policy.common.parameters.annotations.Valid;
59 import org.onap.policy.models.decisions.concepts.DecisionRequest;
60 import org.onap.policy.models.decisions.concepts.DecisionResponse;
61 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
62 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
63 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
64 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
65 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
66 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class GuardTranslator implements ToscaPolicyTranslator {
71 private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslator.class);
74 // common guard property fields
76 public static final String FIELD_ACTOR = "actor";
77 public static final String FIELD_OPERATION = "operation";
78 public static final String FIELD_CONTROLLOOP = "id";
79 public static final String FIELD_TIMERANGE = "timeRange";
82 // frequency property fields
84 public static final String FIELD_TIMEWINDOW = "timeWindow";
85 public static final String FIELD_TIMEUNITS = "timeUnits";
86 public static final String FIELD_LIMIT = "limit";
89 // minmax property fields
91 public static final String FIELD_TARGET = "target";
92 public static final String FIELD_MIN = "min";
93 public static final String FIELD_MAX = "max";
96 // blacklist property fields
98 public static final String FIELD_BLACKLIST = "blacklist";
101 // filter property fields
103 public static final String FIELD_FILTER_WHITELIST = "whitelist";
104 public static final String FIELD_FILTER_ALGORITHM = "algorithm";
105 public static final String FIELD_FILTER_FILTERS = "filters";
106 public static final String FIELD_FILTER_FIELD = "field";
107 public static final String FIELD_FILTER_FUNCTION = "function";
108 public static final String FIELD_FILTER_FILTER = "filter";
109 public static final String FIELD_FILTER_BLACKLIST = "blacklist";
111 public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter";
112 public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax";
113 public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist";
114 public static final String POLICYTYPE_FILTER = "onap.policies.controlloop.guard.common.Filter";
117 // Variable definitions
119 private static final String VARIABLE_TIMEINRANGE = "timeInRange";
121 public GuardTranslator() {
126 * Convert the policy.
129 public Object convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
131 // Policy name should be at the root
133 String policyName = toscaPolicy.getMetadata().get("policy-id");
135 // Set it as the policy ID
137 var newPolicyType = new PolicyType();
138 newPolicyType.setPolicyId(policyName);
140 // Optional description
142 newPolicyType.setDescription(toscaPolicy.getDescription());
144 // There should be a metadata section
146 this.fillMetadataSection(newPolicyType, toscaPolicy.getMetadata());
148 // There should be properties metadata section
150 if (toscaPolicy.getProperties() == null) {
151 throw new ToscaPolicyConversionException("no properties specified on guard policy: " + policyName);
154 // Generate the TargetType - add true if not blacklist
156 newPolicyType.setTarget(this.generateTargetType(toscaPolicy.getProperties(),
157 ! POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())));
159 // Add specific's per guard policy type
161 if (POLICYTYPE_FREQUENCY.equals(toscaPolicy.getType())) {
162 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
163 generateFrequencyRules(toscaPolicy, policyName, newPolicyType);
164 } else if (POLICYTYPE_MINMAX.equals(toscaPolicy.getType())) {
165 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
166 generateMinMaxRules(toscaPolicy, policyName, newPolicyType);
167 } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) {
168 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
169 generateBlacklistRules(toscaPolicy, policyName, newPolicyType);
170 } else if (POLICYTYPE_FILTER.equals(toscaPolicy.getType())) {
171 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue());
172 generateFilterRules(toscaPolicy, policyName, newPolicyType);
174 throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType());
177 // Add in our variable definition
179 VariableReferenceType variable = this.createTimeRangeVariable(toscaPolicy.getProperties(), newPolicyType);
180 if (variable != null) {
182 // Update all the rules to have conditions for this variable
184 this.addVariableToConditionTypes(variable, newPolicyType);
186 return newPolicyType;
190 * This method iterates through all the existing rules, adding in a conditionType that will test
191 * whether the Variable is true or false. Any existing ConditionType will be updated to AND with the
194 * @param variable VariableDefinitionType to add
195 * @param newPolicyType PolicyType that will be updated
197 protected void addVariableToConditionTypes(VariableReferenceType variable,
198 PolicyType newPolicyType) {
200 // Iterate through the rules
202 for (Object objectType : newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
203 if (objectType instanceof RuleType) {
204 RuleType rule = (RuleType) objectType;
205 if (rule.getCondition() == null) {
207 // No condition already, just create and add a new one
209 var condition = new ConditionType();
210 condition.setExpression(new ObjectFactory().createVariableReference(variable));
211 rule.setCondition(condition);
214 // Need to create a new ConditionType that treats all the expressions as an AND
215 // with the Variable.
217 rule.setCondition(ToscaPolicyTranslatorUtils.addVariableToCondition(rule.getCondition(), variable,
218 XACML3.ID_FUNCTION_AND));
228 public Request convertRequest(DecisionRequest request) throws ToscaPolicyConversionException {
229 LOGGER.info("Converting Request {}", request);
231 return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request));
232 } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
233 throw new ToscaPolicyConversionException("Failed to convert DecisionRequest", e);
241 public DecisionResponse convertResponse(Response xacmlResponse) {
242 LOGGER.info("Converting Response {}", xacmlResponse);
243 var decisionResponse = new DecisionResponse();
245 // Iterate through all the results
247 for (Result xacmlResult : xacmlResponse.getResults()) {
251 if (xacmlResult.getDecision() == Decision.PERMIT) {
253 // Just simply return a Permit response
255 decisionResponse.setStatus(Decision.PERMIT.toString());
256 } else if (xacmlResult.getDecision() == Decision.DENY) {
258 // Just simply return a Deny response
260 decisionResponse.setStatus(Decision.DENY.toString());
263 // There is no guard policy, so we return a permit
265 decisionResponse.setStatus(Decision.PERMIT.toString());
269 return decisionResponse;
273 * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
275 * @param policy Policy Object to store the metadata
276 * @param map The Metadata TOSCA Map
277 * @return Same Policy Object
279 protected PolicyType fillMetadataSection(PolicyType policy, Map<String, String> map) {
281 // NOTE: The models code ensures the metadata section ALWAYS exists
284 // Add in the Policy Version
286 policy.setVersion(map.get("policy-version"));
291 * Generate the targettype for the policy. Optional to add MatchType for the target. eg. the
292 * blacklist policy type uses the target in a different manner.
294 * @param properties TOSCA properties object
295 * @param addTargets true to go ahead and add target to the match list.
296 * @return TargetType object
297 * @throws ToscaPolicyConversionException if there is a missing property
299 protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets)
300 throws ToscaPolicyConversionException {
302 // Decode the definition from the policy's properties
304 TargetTypeDefinition targetTypeDef =
305 ToscaPolicyTranslatorUtils.decodeProperties(properties, TargetTypeDefinition.class);
307 // Go through potential properties
309 var allOf = new AllOfType();
310 if (targetTypeDef.getActor() != null) {
311 addMatch(allOf, targetTypeDef.getActor(), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
313 if (targetTypeDef.getOperation() != null) {
314 addMatch(allOf, targetTypeDef.getOperation(), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
316 if (addTargets && targetTypeDef.getTarget() != null) {
317 addMatch(allOf, targetTypeDef.getTarget(), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
319 if (targetTypeDef.getId() != null) {
320 addMatch(allOf, targetTypeDef.getId(), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
325 var target = new TargetType();
326 var anyOf = new AnyOfType();
327 anyOf.getAllOf().add(allOf);
328 target.getAnyOf().add(anyOf);
332 @SuppressWarnings("unchecked")
333 protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
334 if (value instanceof String) {
335 if (".*".equals(value.toString())) {
337 // There's no point to even have a match
344 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
345 XACML3.ID_FUNCTION_STRING_EQUAL,
347 XACML3.ID_DATATYPE_STRING,
349 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
351 allOf.getMatch().add(match);
355 if (value instanceof Collection) {
356 ((Collection<String>) value).forEach(val -> {
357 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
358 XACML3.ID_FUNCTION_STRING_EQUAL,
360 XACML3.ID_DATATYPE_STRING,
362 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
364 allOf.getMatch().add(match);
370 protected void addTimeRangeMatch(AllOfType allOf, TimeRange timeRange)
371 throws ToscaPolicyConversionException {
373 var matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
374 XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL,
375 timeRange.getStartTime(),
376 XACML3.ID_DATATYPE_TIME,
377 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
378 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
380 allOf.getMatch().add(matchStart);
382 var matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
383 XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL,
384 timeRange.getEndTime(),
385 XACML3.ID_DATATYPE_TIME,
386 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
387 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
389 allOf.getMatch().add(matchEnd);
392 protected VariableReferenceType createTimeRangeVariable(Map<String, Object> properties, PolicyType newPolicyType)
393 throws ToscaPolicyConversionException {
395 // Decode the definition from the policy's properties
397 TimeRangeDefinition timeRangeDef =
398 ToscaPolicyTranslatorUtils.decodeProperties(properties, TimeRangeDefinition.class);
399 TimeRange timeRange = timeRangeDef.getTimeRange();
400 if (timeRange == null) {
404 // Should also be parseable as an ISO8601 timestamp
406 var startTimeObject = parseTimestamp(timeRange.getStartTime());
407 var endTimeObject = parseTimestamp(timeRange.getEndTime());
409 // They should be the same object types. We cannot establish a range
410 // between an OffsetDateTime and an OffsetTime
412 if (! startTimeObject.getClass().equals(endTimeObject.getClass())) {
413 throw new ToscaPolicyConversionException("start_time and end_time class types do not match");
416 // Create the inner timeInRange ApplyType
418 ApplyType timeInRange = ToscaPolicyTranslatorUtils.generateTimeInRange(timeRange.getStartTime(),
419 timeRange.getEndTime(), true);
420 var variable = new VariableDefinitionType();
421 variable.setVariableId(VARIABLE_TIMEINRANGE);
422 variable.setExpression(new ObjectFactory().createApply(timeInRange));
424 // Add it to the policy
426 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(variable);
428 // Create and return the reference to the variable
430 var reference = new VariableReferenceType();
431 reference.setVariableId(variable.getVariableId());
435 protected Object parseTimestamp(String string) throws ToscaPolicyConversionException {
437 // First see if it is a full datetime object
440 return OffsetDateTime.parse(string);
441 } catch (Exception e) {
442 LOGGER.warn("timestamp {} could not be parsed. This may not be an error.", string, e);
445 // May only be a time object
448 return OffsetTime.parse(string);
449 } catch (Exception e) {
450 throw new ToscaPolicyConversionException("timestamp " + string + " could not be parsed ", e);
454 protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
455 throws ToscaPolicyConversionException {
457 // Decode the definition from the policy's properties
459 FrequencyDefinition frequencyDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
460 FrequencyDefinition.class);
462 // See if its possible to generate a count
464 String timeWindow = null;
465 if (frequencyDef.getTimeWindow() != null) {
466 timeWindow = frequencyDef.getTimeWindow().toString();
471 final ApplyType countCheck =
472 generateCountCheck(frequencyDef.getLimit(), timeWindow, frequencyDef.getTimeUnits());
474 // Create our condition
476 final var condition = new ConditionType();
477 condition.setExpression(new ObjectFactory().createApply(countCheck));
480 // Now we can create our rule
482 var frequencyRule = new RuleType();
483 frequencyRule.setDescription("Frequency limit permit rule");
484 frequencyRule.setRuleId(policyName + ":frequency");
485 frequencyRule.setEffect(EffectType.PERMIT);
486 frequencyRule.setTarget(new TargetType());
490 frequencyRule.setCondition(condition);
492 // Add the rule to the policy
494 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule);
497 protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
498 var designator = new AttributeDesignatorType();
499 designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
500 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
501 designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
503 // Setup issuer - used by the operations PIP to determine
504 // how to do the database query.
506 String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX
507 + CountRecentOperationsPip.ISSUER_NAME
508 + ":tw:" + timeWindow + ":" + timeUnits;
509 designator.setIssuer(issuer);
511 var valueLimit = new AttributeValueType();
512 valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
514 // Yes really use toString(), the marshaller will
515 // throw an exception if this is an integer object
518 valueLimit.getContent().add(limit.toString());
520 var factory = new ObjectFactory();
522 var applyOneAndOnly = new ApplyType();
523 applyOneAndOnly.setDescription("Unbag the limit");
524 applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
525 applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
527 var applyLessThan = new ApplyType();
528 applyLessThan.setDescription("return true if current count is less than.");
529 applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue());
530 applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly));
531 applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit));
533 return applyLessThan;
536 protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
537 throws ToscaPolicyConversionException {
539 // Decode the definition from the policy's properties
541 MinMaxDefinition minMaxDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
542 MinMaxDefinition.class);
546 var matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
547 XACML3.ID_FUNCTION_STRING_EQUAL,
548 minMaxDef.getTarget(),
549 XACML3.ID_DATATYPE_STRING,
550 ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
551 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
553 // For the min, if the # of instances is less than the minimum
554 // then allow the scale.
556 if (minMaxDef.getMin() != null) {
557 var matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
558 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
559 minMaxDef.getMin().toString(),
560 XACML3.ID_DATATYPE_INTEGER,
561 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
562 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
564 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
565 generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum"));
567 if (minMaxDef.getMax() != null) {
568 var matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
569 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
570 minMaxDef.getMax().toString(),
571 XACML3.ID_DATATYPE_INTEGER,
572 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
573 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
575 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
576 generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum"));
579 // Do we have at least a min or max?
581 if (minMaxDef.getMin() == null && minMaxDef.getMax() == null) {
582 throw new ToscaPolicyConversionException("Missing min or max field in minmax policy");
586 protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) {
587 var allOf = new AllOfType();
588 allOf.getMatch().add(matchTarget);
589 allOf.getMatch().add(matchMinOrMax);
590 var anyOf = new AnyOfType();
591 anyOf.getAllOf().add(allOf);
592 var target = new TargetType();
593 target.getAnyOf().add(anyOf);
594 var minMaxRule = new RuleType();
595 minMaxRule.setEffect(EffectType.PERMIT);
596 minMaxRule.setDescription(desc);
597 minMaxRule.setRuleId(ruleId);
598 minMaxRule.setTarget(target);
602 protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
603 throws ToscaPolicyConversionException {
605 // Decode the definition from the policy's properties
607 BlacklistDefinition blacklistDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
608 BlacklistDefinition.class);
610 // Iterate the entries and create individual AnyOf so each entry is
613 var target = new TargetType();
614 var anyOf = new AnyOfType();
615 for (Object blacklisted : blacklistDef.blacklist) {
616 var allOf = new AllOfType();
617 this.addMatch(allOf, blacklisted, ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
618 anyOf.getAllOf().add(allOf);
620 target.getAnyOf().add(anyOf);
622 // Create our rule and add the target
624 var blacklistRule = new RuleType();
625 blacklistRule.setEffect(EffectType.DENY);
626 blacklistRule.setDescription("blacklist the entities");
627 blacklistRule.setRuleId(policyName + ":blacklist");
628 blacklistRule.setTarget(target);
630 // Add the rule to the policy
632 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule);
635 protected void generateFilterRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
636 throws ToscaPolicyConversionException {
638 // Decode the definition from the policy's properties
640 FilterDefinition filterDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
641 FilterDefinition.class);
643 // Set the combining algorithm
645 switch (filterDef.getAlgorithm()) {
646 case "whitelist-overrides":
647 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_OVERRIDES.stringValue());
649 case "blacklist-overrides":
650 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_OVERRIDES.stringValue());
653 throw new ToscaPolicyConversionException(
654 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
657 // Iterate the filters
660 for (FilterAttribute filterAttributes : filterDef.filters) {
662 // Check fields requiring extra validation
664 String field = validateFilterPropertyField(filterAttributes.getField());
665 Identifier function = validateFilterPropertyFunction(filterAttributes.getFunction());
667 // Create our filter rule
669 RuleType filterRule = createFilterRule(policyName + ":rule" + ruleId++, field, filterAttributes.getFilter(),
670 function, filterAttributes.getBlacklist());
672 // Add the rule to the policy
674 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(filterRule);
678 protected String validateFilterPropertyField(String field)
679 throws ToscaPolicyConversionException {
680 String fieldLowerCase = field.toLowerCase();
681 switch (fieldLowerCase) {
682 case "generic-vnf.vnf-name":
683 case "generic-vnf.vnf-id":
684 case "generic-vnf.vnf-type":
685 case "generic-vnf.nf-naming-code":
686 case "vserver.vserver-id":
687 case "cloud-region.cloud-region-id":
688 return fieldLowerCase;
690 throw new ToscaPolicyConversionException("Unexpected value for field in filter");
694 protected Identifier validateFilterPropertyFunction(String function)
695 throws ToscaPolicyConversionException {
696 switch (function.toLowerCase()) {
698 return XACML3.ID_FUNCTION_STRING_EQUAL;
699 case "string-equal-ignore-case":
700 return XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE;
701 case "string-regexp-match":
702 return XACML3.ID_FUNCTION_STRING_REGEXP_MATCH;
703 case "string-contains":
704 return XACML3.ID_FUNCTION_STRING_CONTAINS;
705 case "string-greater-than":
706 return XACML3.ID_FUNCTION_STRING_GREATER_THAN;
707 case "string-greater-than-or-equal":
708 return XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL;
709 case "string-less-than":
710 return XACML3.ID_FUNCTION_STRING_LESS_THAN;
711 case "string-less-than-or-equal":
712 return XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL;
713 case "string-starts-with":
714 return XACML3.ID_FUNCTION_STRING_STARTS_WITH;
715 case "string-ends-with":
716 return XACML3.ID_FUNCTION_STRING_ENDS_WITH;
718 throw new ToscaPolicyConversionException("Unexpected value for function in filter");
722 protected RuleType createFilterRule(String ruleId, String field, String filter, Identifier function,
723 boolean isBlacklisted) {
724 var rule = new RuleType();
725 rule.setRuleId(ruleId);
730 var matchFilter = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
733 XACML3.ID_DATATYPE_STRING,
734 new IdentifierImpl(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID + field),
735 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE
737 var allOf = new AllOfType();
738 allOf.getMatch().add(matchFilter);
739 var anyOf = new AnyOfType();
740 anyOf.getAllOf().add(allOf);
741 var target = new TargetType();
742 target.getAnyOf().add(anyOf);
744 rule.setTarget(target);
747 rule.setEffect(EffectType.DENY);
749 rule.setEffect(EffectType.PERMIT);
755 public static class TimeRangeDefinition {
756 private @Valid TimeRange timeRange;
760 public static class TargetTypeDefinition {
761 private String actor;
762 private String operation;
763 private String target;
770 public static class TimeRange {
771 @SerializedName("start_time")
772 private String startTime;
774 @SerializedName("end_time")
775 private String endTime;
779 public static class FrequencyDefinition {
781 private Integer limit;
782 private Integer timeWindow;
783 private String timeUnits;
787 public static class MinMaxDefinition {
789 private String target;
796 public static class BlacklistDefinition {
797 private List<@NotNull Object> blacklist;
802 public static class FilterDefinition {
803 private String algorithm;
804 private List<@NotNull @Valid FilterAttribute> filters;
809 public static class FilterAttribute {
810 private String field;
811 private String filter;
812 private String function;
813 private Boolean blacklist;