2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2020, 2023 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 = String.valueOf(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 rule) {
203 if (rule.getCondition() == null) {
205 // No condition already, just create and add a new one
207 var condition = new ConditionType();
208 condition.setExpression(new ObjectFactory().createVariableReference(variable));
209 rule.setCondition(condition);
212 // Need to create a new ConditionType that treats all the expressions as an AND
213 // with the Variable.
215 rule.setCondition(ToscaPolicyTranslatorUtils.addVariableToCondition(rule.getCondition(), variable,
216 XACML3.ID_FUNCTION_AND));
226 public Request convertRequest(DecisionRequest request) throws ToscaPolicyConversionException {
227 LOGGER.info("Converting Request {}", request);
229 return RequestParser.parseRequest(GuardPolicyRequest.createInstance(request));
230 } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
231 throw new ToscaPolicyConversionException("Failed to convert DecisionRequest", e);
239 public DecisionResponse convertResponse(Response xacmlResponse) {
240 LOGGER.info("Converting Response {}", xacmlResponse);
241 var decisionResponse = new DecisionResponse();
243 // Iterate through all the results
245 for (Result xacmlResult : xacmlResponse.getResults()) {
249 if (xacmlResult.getDecision() == Decision.PERMIT) {
251 // Just simply return a Permit response
253 decisionResponse.setStatus(Decision.PERMIT.toString());
254 } else if (xacmlResult.getDecision() == Decision.DENY) {
256 // Just simply return a Deny response
258 decisionResponse.setStatus(Decision.DENY.toString());
261 // There is no guard policy, so we return a permit
263 decisionResponse.setStatus(Decision.PERMIT.toString());
267 return decisionResponse;
271 * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
273 * @param policy Policy Object to store the metadata
274 * @param map The Metadata TOSCA Map
275 * @return Same Policy Object
277 protected PolicyType fillMetadataSection(PolicyType policy, Map<String, Object> map) {
279 // NOTE: The models code ensures the metadata section ALWAYS exists
282 // Add in the Policy Version
284 policy.setVersion(String.valueOf(map.get("policy-version")));
289 * Generate the targetType for the policy. Optional to add MatchType for the target. eg. the
290 * blacklist policy type uses the target in a different manner.
292 * @param properties TOSCA properties object
293 * @param addTargets true to go ahead and add target to the match list.
294 * @return TargetType object
295 * @throws ToscaPolicyConversionException if there is a missing property
297 protected TargetType generateTargetType(Map<String, Object> properties, boolean addTargets)
298 throws ToscaPolicyConversionException {
300 // Decode the definition from the policy's properties
302 TargetTypeDefinition targetTypeDef =
303 ToscaPolicyTranslatorUtils.decodeProperties(properties, TargetTypeDefinition.class);
305 // Go through potential properties
307 var allOf = new AllOfType();
308 if (targetTypeDef.getActor() != null) {
309 addMatch(allOf, targetTypeDef.getActor(), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
311 if (targetTypeDef.getOperation() != null) {
312 addMatch(allOf, targetTypeDef.getOperation(), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
314 if (addTargets && targetTypeDef.getTarget() != null) {
315 addMatch(allOf, targetTypeDef.getTarget(), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
317 if (targetTypeDef.getId() != null) {
318 addMatch(allOf, targetTypeDef.getId(), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
323 var target = new TargetType();
324 var anyOf = new AnyOfType();
325 anyOf.getAllOf().add(allOf);
326 target.getAnyOf().add(anyOf);
330 @SuppressWarnings("unchecked")
331 protected AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
332 if (value instanceof String) {
333 if (".*".equals(value.toString())) {
335 // There's no point to even have a match
342 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
343 XACML3.ID_FUNCTION_STRING_EQUAL,
345 XACML3.ID_DATATYPE_STRING,
347 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
349 allOf.getMatch().add(match);
353 if (value instanceof Collection) {
354 ((Collection<String>) value).forEach(val -> {
355 var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
356 XACML3.ID_FUNCTION_STRING_EQUAL,
358 XACML3.ID_DATATYPE_STRING,
360 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
362 allOf.getMatch().add(match);
368 protected void addTimeRangeMatch(AllOfType allOf, TimeRange timeRange) {
370 var matchStart = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
371 XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL,
372 timeRange.getStartTime(),
373 XACML3.ID_DATATYPE_TIME,
374 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
375 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
377 allOf.getMatch().add(matchStart);
379 var matchEnd = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
380 XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL,
381 timeRange.getEndTime(),
382 XACML3.ID_DATATYPE_TIME,
383 XACML3.ID_ENVIRONMENT_CURRENT_TIME,
384 XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT);
386 allOf.getMatch().add(matchEnd);
389 protected VariableReferenceType createTimeRangeVariable(Map<String, Object> properties, PolicyType newPolicyType)
390 throws ToscaPolicyConversionException {
392 // Decode the definition from the policy's properties
394 TimeRangeDefinition timeRangeDef =
395 ToscaPolicyTranslatorUtils.decodeProperties(properties, TimeRangeDefinition.class);
396 TimeRange timeRange = timeRangeDef.getTimeRange();
397 if (timeRange == null) {
401 // Should also be parseable as an ISO8601 timestamp
403 var startTimeObject = parseTimestamp(timeRange.getStartTime());
404 var endTimeObject = parseTimestamp(timeRange.getEndTime());
406 // They should be the same object types. We cannot establish a range
407 // between an OffsetDateTime and an OffsetTime
409 if (!startTimeObject.getClass().equals(endTimeObject.getClass())) {
410 throw new ToscaPolicyConversionException("start_time and end_time class types do not match");
413 // Create the inner timeInRange ApplyType
415 ApplyType timeInRange = ToscaPolicyTranslatorUtils.generateTimeInRange(timeRange.getStartTime(),
416 timeRange.getEndTime(), true);
417 var variable = new VariableDefinitionType();
418 variable.setVariableId(VARIABLE_TIMEINRANGE);
419 variable.setExpression(new ObjectFactory().createApply(timeInRange));
421 // Add it to the policy
423 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(variable);
425 // Create and return the reference to the variable
427 var reference = new VariableReferenceType();
428 reference.setVariableId(variable.getVariableId());
432 protected Object parseTimestamp(String string) throws ToscaPolicyConversionException {
434 // First see if it is a full datetime object
437 return OffsetDateTime.parse(string);
438 } catch (Exception e) {
439 LOGGER.warn("timestamp {} could not be parsed. This may not be an error.", string, e);
442 // May only be a time object
445 return OffsetTime.parse(string);
446 } catch (Exception e) {
447 throw new ToscaPolicyConversionException("timestamp " + string + " could not be parsed ", e);
451 protected void generateFrequencyRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
452 throws ToscaPolicyConversionException {
454 // Decode the definition from the policy's properties
456 FrequencyDefinition frequencyDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
457 FrequencyDefinition.class);
459 // See if its possible to generate a count
461 String timeWindow = null;
462 if (frequencyDef.getTimeWindow() != null) {
463 timeWindow = frequencyDef.getTimeWindow().toString();
468 final ApplyType countCheck =
469 generateCountCheck(frequencyDef.getLimit(), timeWindow, frequencyDef.getTimeUnits());
471 // Create our condition
473 final var condition = new ConditionType();
474 condition.setExpression(new ObjectFactory().createApply(countCheck));
477 // Now we can create our rule
479 var frequencyRule = new RuleType();
480 frequencyRule.setDescription("Frequency limit permit rule");
481 frequencyRule.setRuleId(policyName + ":frequency");
482 frequencyRule.setEffect(EffectType.PERMIT);
483 frequencyRule.setTarget(new TargetType());
487 frequencyRule.setCondition(condition);
489 // Add the rule to the policy
491 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(frequencyRule);
494 protected ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
495 var designator = new AttributeDesignatorType();
496 designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
497 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
498 designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
500 // Setup issuer - used by the operations PIP to determine
501 // how to do the database query.
503 String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX
504 + CountRecentOperationsPip.ISSUER_NAME
505 + ":tw:" + timeWindow + ":" + timeUnits;
506 designator.setIssuer(issuer);
508 var valueLimit = new AttributeValueType();
509 valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
511 // Yes really use toString(), the marshaller will
512 // throw an exception if this is an integer object
515 valueLimit.getContent().add(limit.toString());
517 var factory = new ObjectFactory();
519 var applyOneAndOnly = new ApplyType();
520 applyOneAndOnly.setDescription("Unbag the limit");
521 applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
522 applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
524 var applyLessThan = new ApplyType();
525 applyLessThan.setDescription("return true if current count is less than.");
526 applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue());
527 applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly));
528 applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit));
530 return applyLessThan;
533 protected void generateMinMaxRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
534 throws ToscaPolicyConversionException {
536 // Decode the definition from the policy's properties
538 MinMaxDefinition minMaxDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
539 MinMaxDefinition.class);
543 var matchTarget = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
544 XACML3.ID_FUNCTION_STRING_EQUAL,
545 minMaxDef.getTarget(),
546 XACML3.ID_DATATYPE_STRING,
547 ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
548 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
550 // For the min, if the # of instances is less than the minimum
551 // then allow the scale.
553 if (minMaxDef.getMin() != null) {
554 var matchMin = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
555 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
556 minMaxDef.getMin().toString(),
557 XACML3.ID_DATATYPE_INTEGER,
558 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
559 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
561 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
562 generateMinMaxRule(matchTarget, matchMin, policyName + ":minrule", "check minimum"));
564 if (minMaxDef.getMax() != null) {
565 var matchMax = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
566 XACML3.ID_FUNCTION_INTEGER_GREATER_THAN,
567 minMaxDef.getMax().toString(),
568 XACML3.ID_DATATYPE_INTEGER,
569 ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT,
570 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
572 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(
573 generateMinMaxRule(matchTarget, matchMax, policyName + ":maxrule", "check maximum"));
576 // Do we have at least a min or max?
578 if (minMaxDef.getMin() == null && minMaxDef.getMax() == null) {
579 throw new ToscaPolicyConversionException("Missing min or max field in minmax policy");
583 protected RuleType generateMinMaxRule(MatchType matchTarget, MatchType matchMinOrMax, String ruleId, String desc) {
584 var allOf = new AllOfType();
585 allOf.getMatch().add(matchTarget);
586 allOf.getMatch().add(matchMinOrMax);
587 var anyOf = new AnyOfType();
588 anyOf.getAllOf().add(allOf);
589 var target = new TargetType();
590 target.getAnyOf().add(anyOf);
591 var minMaxRule = new RuleType();
592 minMaxRule.setEffect(EffectType.PERMIT);
593 minMaxRule.setDescription(desc);
594 minMaxRule.setRuleId(ruleId);
595 minMaxRule.setTarget(target);
599 protected void generateBlacklistRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
600 throws ToscaPolicyConversionException {
602 // Decode the definition from the policy's properties
604 BlacklistDefinition blacklistDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
605 BlacklistDefinition.class);
607 // Iterate the entries and create individual AnyOf so each entry is
610 var target = new TargetType();
611 var anyOf = new AnyOfType();
612 for (Object blacklisted : blacklistDef.blacklist) {
613 var allOf = new AllOfType();
614 this.addMatch(allOf, blacklisted, ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
615 anyOf.getAllOf().add(allOf);
617 target.getAnyOf().add(anyOf);
619 // Create our rule and add the target
621 var blacklistRule = new RuleType();
622 blacklistRule.setEffect(EffectType.DENY);
623 blacklistRule.setDescription("blacklist the entities");
624 blacklistRule.setRuleId(policyName + ":blacklist");
625 blacklistRule.setTarget(target);
627 // Add the rule to the policy
629 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule);
632 protected void generateFilterRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType)
633 throws ToscaPolicyConversionException {
635 // Decode the definition from the policy's properties
637 FilterDefinition filterDef = ToscaPolicyTranslatorUtils.decodeProperties(toscaPolicy.getProperties(),
638 FilterDefinition.class);
640 // Set the combining algorithm
642 switch (filterDef.getAlgorithm()) {
643 case "whitelist-overrides":
644 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_OVERRIDES.stringValue());
646 case "blacklist-overrides":
647 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_OVERRIDES.stringValue());
650 throw new ToscaPolicyConversionException(
651 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
654 // Iterate the filters
657 for (FilterAttribute filterAttributes : filterDef.filters) {
659 // Check fields requiring extra validation
661 String field = validateFilterPropertyField(filterAttributes.getField());
662 Identifier function = validateFilterPropertyFunction(filterAttributes.getFunction());
664 // Create our filter rule
666 RuleType filterRule = createFilterRule(policyName + ":rule" + ruleId++, field, filterAttributes.getFilter(),
667 function, filterAttributes.getBlacklist());
669 // Add the rule to the policy
671 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(filterRule);
675 protected String validateFilterPropertyField(String field)
676 throws ToscaPolicyConversionException {
677 String fieldLowerCase = field.toLowerCase();
678 return switch (fieldLowerCase) {
679 case "generic-vnf.vnf-name", "generic-vnf.vnf-id", "generic-vnf.vnf-type", "generic-vnf.nf-naming-code",
680 "vserver.vserver-id", "cloud-region.cloud-region-id" -> fieldLowerCase;
681 default -> throw new ToscaPolicyConversionException("Unexpected value for field in filter");
685 protected Identifier validateFilterPropertyFunction(String function)
686 throws ToscaPolicyConversionException {
687 return switch (function.toLowerCase()) {
688 case "string-equal" -> XACML3.ID_FUNCTION_STRING_EQUAL;
689 case "string-equal-ignore-case" -> XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE;
690 case "string-regexp-match" -> XACML3.ID_FUNCTION_STRING_REGEXP_MATCH;
691 case "string-contains" -> XACML3.ID_FUNCTION_STRING_CONTAINS;
692 case "string-greater-than" -> XACML3.ID_FUNCTION_STRING_GREATER_THAN;
693 case "string-greater-than-or-equal" -> XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL;
694 case "string-less-than" -> XACML3.ID_FUNCTION_STRING_LESS_THAN;
695 case "string-less-than-or-equal" -> XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL;
696 case "string-starts-with" -> XACML3.ID_FUNCTION_STRING_STARTS_WITH;
697 case "string-ends-with" -> XACML3.ID_FUNCTION_STRING_ENDS_WITH;
698 default -> throw new ToscaPolicyConversionException("Unexpected value for function in filter");
702 protected RuleType createFilterRule(String ruleId, String field, String filter, Identifier function,
703 boolean isBlacklisted) {
704 var rule = new RuleType();
705 rule.setRuleId(ruleId);
710 var matchFilter = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
713 XACML3.ID_DATATYPE_STRING,
714 new IdentifierImpl(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID + field),
715 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE
717 var allOf = new AllOfType();
718 allOf.getMatch().add(matchFilter);
719 var anyOf = new AnyOfType();
720 anyOf.getAllOf().add(allOf);
721 var target = new TargetType();
722 target.getAnyOf().add(anyOf);
724 rule.setTarget(target);
727 rule.setEffect(EffectType.DENY);
729 rule.setEffect(EffectType.PERMIT);
735 public static class TimeRangeDefinition {
736 private @Valid TimeRange timeRange;
740 public static class TargetTypeDefinition {
741 private String actor;
742 private String operation;
743 private String target;
750 public static class TimeRange {
751 @SerializedName("start_time")
752 private String startTime;
754 @SerializedName("end_time")
755 private String endTime;
759 public static class FrequencyDefinition {
761 private Integer limit;
762 private Integer timeWindow;
763 private String timeUnits;
767 public static class MinMaxDefinition {
769 private String target;
776 public static class BlacklistDefinition {
777 private List<@NotNull Object> blacklist;
782 public static class FilterDefinition {
783 private String algorithm;
784 private List<@NotNull @Valid FilterAttribute> filters;
789 public static class FilterAttribute {
790 private String field;
791 private String filter;
792 private String function;
793 private Boolean blacklist;