From ad9d827a43211c087fe4bcf575134aea3a5b316e Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Mon, 17 Aug 2020 16:45:30 -0400 Subject: [PATCH] Add new guard filter policy type feature * Added new Policy Guard filter Policy type. * Enhanced translator tests to ensure bad filter policies are detected. * Added new filter application test to ensure new guard propertly creates xacml policies. Issue-ID: POLICY-2590 Change-Id: Ifc047a33084ce45b67be98a61f660d7a8c9d8615 Signed-off-by: Pamela Dragosh --- .../pdp/application/guard/GuardPdpApplication.java | 3 + .../pdp/application/guard/GuardPolicyRequest.java | 38 +++++ .../pdp/application/guard/GuardTranslator.java | 183 ++++++++++++++++++++- .../application/guard/GuardPdpApplicationTest.java | 75 ++++++++- .../application/guard/GuardPolicyRequestTest.java | 20 +++ .../pdp/application/guard/GuardTranslatorTest.java | 74 +++++++++ .../src/test/resources/requests/guard.filter.json | 22 +++ .../src/test/resources/requests/guard.vfCount.json | 8 +- .../src/test/resources/test-bad-policies.yaml | 151 +++++++++++++---- .../guard/src/test/resources/test-policies.yaml | 54 ++++++ .../test/resources/test.policy.guard.filters.yaml | 39 +++++ .../main/rest/XacmlPdpApplicationManagerTest.java | 4 +- 12 files changed, 636 insertions(+), 35 deletions(-) create mode 100644 applications/guard/src/test/resources/requests/guard.filter.json create mode 100644 applications/guard/src/test/resources/test.policy.guard.filters.yaml diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java index 9f954766..982c14b7 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java @@ -58,6 +58,9 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( GuardTranslator.POLICYTYPE_BLACKLIST, STRING_VERSION100)); + this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( + GuardTranslator.POLICYTYPE_FILTER, + STRING_VERSION100)); this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", STRING_VERSION100)); diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java index c516877a..72c8ddd2 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequest.java @@ -70,6 +70,26 @@ public class GuardPolicyRequest { @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:vf-count") private Integer vfCount; + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:generic-vnf.vnf-name") + private String vnfName; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:generic-vnf.vnf-id") + private String vnfId; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:generic-vnf.vnf-type") + private String vnfType; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:generic-vnf.nf-naming-code") + private String vnfNfNamingCode; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:vserver.vserver-id") + private String vserverId; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:cloud-region.cloud-region-id") + private String cloudRegionId; + + public static final String PREFIX_RESOURCE_ATTRIBUTE_ID = "urn:org:onap:guard:target:"; + public GuardPolicyRequest() { super(); } @@ -138,6 +158,24 @@ public class GuardPolicyRequest { throw new ToscaPolicyConversionException("Failed to decode vfCount", e); } } + if (guard.containsKey("generic-vnf.vnf-name")) { + request.vnfName = guard.get("generic-vnf.vnf-name").toString(); + } + if (guard.containsKey("generic-vnf.vnf-id")) { + request.vnfId = guard.get("generic-vnf.vnf-id").toString(); + } + if (guard.containsKey("generic-vnf.vnf-type")) { + request.vnfType = guard.get("generic-vnf.vnf-type").toString(); + } + if (guard.containsKey("generic-vnf.nf-naming-code")) { + request.vnfNfNamingCode = guard.get("generic-vnf.nf-naming-code").toString(); + } + if (guard.containsKey("vserver.vserver-id")) { + request.vserverId = guard.get("vserver.vserver-id").toString(); + } + if (guard.containsKey("cloud-region.cloud-region-id")) { + request.cloudRegionId = guard.get("cloud-region.cloud-region-id").toString(); + } return request; } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java index 8699fec0..b3ee36bc 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslator.java @@ -29,6 +29,7 @@ import com.att.research.xacml.api.Request; import com.att.research.xacml.api.Response; import com.att.research.xacml.api.Result; import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.IdentifierImpl; import com.att.research.xacml.std.annotations.RequestParser; import java.util.Collection; import java.util.Map; @@ -85,9 +86,21 @@ public class GuardTranslator implements ToscaPolicyTranslator { // public static final String FIELD_BLACKLIST = "blacklist"; + // + // filter property fields + // + public static final String FIELD_FILTER_WHITELIST = "whitelist"; + public static final String FIELD_FILTER_ALGORITHM = "algorithm"; + public static final String FIELD_FILTER_FILTERS = "filters"; + public static final String FIELD_FILTER_FIELD = "field"; + public static final String FIELD_FILTER_FUNCTION = "function"; + public static final String FIELD_FILTER_FILTER = "filter"; + public static final String FIELD_FILTER_BLACKLIST = "blacklist"; + public static final String POLICYTYPE_FREQUENCY = "onap.policies.controlloop.guard.common.FrequencyLimiter"; public static final String POLICYTYPE_MINMAX = "onap.policies.controlloop.guard.common.MinMax"; public static final String POLICYTYPE_BLACKLIST = "onap.policies.controlloop.guard.common.Blacklist"; + public static final String POLICYTYPE_FILTER = "onap.policies.controlloop.guard.common.Filter"; public GuardTranslator() { super(); @@ -132,6 +145,9 @@ public class GuardTranslator implements ToscaPolicyTranslator { } else if (POLICYTYPE_BLACKLIST.equals(toscaPolicy.getType())) { newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue()); generateBlacklistRules(toscaPolicy, policyName, newPolicyType); + } else if (POLICYTYPE_FILTER.equals(toscaPolicy.getType())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_UNLESS_DENY.stringValue()); + generateFilterRules(toscaPolicy, policyName, newPolicyType); } else { throw new ToscaPolicyConversionException("Unknown guard policy type " + toscaPolicy.getType()); } @@ -513,4 +529,169 @@ public class GuardTranslator implements ToscaPolicyTranslator { newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(blacklistRule); } -} + @SuppressWarnings("unchecked") + protected void generateFilterRules(ToscaPolicy toscaPolicy, String policyName, PolicyType newPolicyType) + throws ToscaPolicyConversionException { + // + // Validate the algorithm + // + if (! toscaPolicy.getProperties().containsKey(FIELD_FILTER_ALGORITHM)) { + throw new ToscaPolicyConversionException("Missing algorithm"); + } + Object algorithm = toscaPolicy.getProperties().get(FIELD_FILTER_ALGORITHM); + if ("whitelist-overrides".equals(algorithm.toString())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_PERMIT_OVERRIDES.stringValue()); + } else if ("blacklist-overrides".equals(algorithm.toString())) { + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_OVERRIDES.stringValue()); + } else { + throw new ToscaPolicyConversionException( + "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides"); + } + // + // Validate the filters exist and have the right properties + // + if (! toscaPolicy.getProperties().containsKey(FIELD_FILTER_FILTERS)) { + throw new ToscaPolicyConversionException("Missing filters"); + } + // + // Get the filters, which should be an array or collection. + // + Object arrayFilters = toscaPolicy.getProperties().get(FIELD_FILTER_FILTERS); + if (!(arrayFilters instanceof Collection)) { + throw new ToscaPolicyConversionException("Filters is not a collection"); + } + // + // Iterate the filters + // + int ruleId = 1; + for (Object filterAttributes : ((Collection) arrayFilters)) { + if (!(filterAttributes instanceof Map)) { + throw new ToscaPolicyConversionException("Filter should be a map"); + } + // + // All fields must be there + // + String field = validateFilterPropertyField((Map) filterAttributes); + String filter = validateFilterPropertyFilter((Map) filterAttributes); + Identifier function = validateFilterPropertyFunction((Map) filterAttributes); + boolean isBlacklisted = validateFilterPropertyBlacklist((Map) filterAttributes); + // + // Create our filter rule + // + RuleType filterRule = createFilterRule(policyName + ":rule" + ruleId++, field, filter, + function, isBlacklisted); + // + // Add the rule to the policy + // + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(filterRule); + } + } + + private String validateFilterPropertyField(Map filterAttributes) + throws ToscaPolicyConversionException { + Object field = filterAttributes.get(FIELD_FILTER_FIELD); + if (field != null) { + switch (field.toString().toLowerCase()) { + case "generic-vnf.vnf-name": + case "generic-vnf.vnf-id": + case "generic-vnf.vnf-type": + case "generic-vnf.nf-naming-code": + case "vserver.vserver-id": + case "cloud-region.cloud-region-id": + return field.toString(); + default: + throw new ToscaPolicyConversionException("Unexpected value for field in filter"); + } + } + throw new ToscaPolicyConversionException("Missing \'field\' from filter"); + } + + private String validateFilterPropertyFilter(Map filterAttributes) + throws ToscaPolicyConversionException { + Object filter = filterAttributes.get(FIELD_FILTER_FILTER); + if (filter != null) { + return filter.toString(); + } + throw new ToscaPolicyConversionException("Missing \'filter\' from filter"); + } + + private Identifier validateFilterPropertyFunction(Map filterAttributes) + throws ToscaPolicyConversionException { + Object function = filterAttributes.get(FIELD_FILTER_FUNCTION); + if (function != null) { + switch (function.toString().toLowerCase()) { + case "string-equal": + return XACML3.ID_FUNCTION_STRING_EQUAL; + case "string-equal-ignore-case": + return XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE; + case "string-regexp-match": + return XACML3.ID_FUNCTION_STRING_REGEXP_MATCH; + case "string-contains": + return XACML3.ID_FUNCTION_STRING_CONTAINS; + case "string-greater-than": + return XACML3.ID_FUNCTION_STRING_GREATER_THAN; + case "string-greater-than-or-equal": + return XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL; + case "string-less-than": + return XACML3.ID_FUNCTION_STRING_LESS_THAN; + case "string-less-than-or-equal": + return XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL; + case "string-starts-with": + return XACML3.ID_FUNCTION_STRING_STARTS_WITH; + case "string-ends-with": + return XACML3.ID_FUNCTION_STRING_ENDS_WITH; + default: + throw new ToscaPolicyConversionException("Unexpected value for function in filter"); + } + } + throw new ToscaPolicyConversionException("Missing \'function\' from filter"); + } + + private boolean validateFilterPropertyBlacklist(Map filterAttributes) + throws ToscaPolicyConversionException { + Object filter = filterAttributes.get(FIELD_FILTER_BLACKLIST); + if (filter != null) { + if ("true".equalsIgnoreCase(filter.toString())) { + return true; + } + if ("false".equalsIgnoreCase(filter.toString())) { + return false; + } + throw new ToscaPolicyConversionException("Unexpected value for blacklist in filter"); + } + throw new ToscaPolicyConversionException("Missing \'blacklist\' from filter"); + } + + private RuleType createFilterRule(String ruleId, String field, String filter, Identifier function, + boolean isBlacklisted) { + RuleType rule = new RuleType(); + rule.setRuleId(ruleId); + + // + // Create the Match + // + MatchType matchFilter = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + function, + filter, + XACML3.ID_DATATYPE_STRING, + new IdentifierImpl(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID + field), + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE + ); + AllOfType allOf = new AllOfType(); + allOf.getMatch().add(matchFilter); + AnyOfType anyOf = new AnyOfType(); + anyOf.getAllOf().add(allOf); + TargetType target = new TargetType(); + target.getAnyOf().add(anyOf); + + rule.setTarget(target); + + if (isBlacklisted) { + rule.setEffect(EffectType.DENY); + } else { + rule.setEffect(EffectType.PERMIT); + } + return rule; + } + +} \ No newline at end of file diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java index e83f4d29..08495a7e 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java @@ -217,7 +217,7 @@ public class GuardPdpApplicationTest { // can support the correct policy types. // assertThat(service.supportedPolicyTypes()).isNotEmpty(); - assertThat(service.supportedPolicyTypes().size()).isEqualTo(4); + assertThat(service.supportedPolicyTypes().size()).isEqualTo(5); assertThat(service.canSupportPolicyType( new ToscaPolicyTypeIdentifier("onap.policies.controlloop.guard.common.FrequencyLimiter", "1.0.0"))) .isTrue(); @@ -237,6 +237,8 @@ public class GuardPdpApplicationTest { assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier("onap.foo", "1.0.1"))).isFalse(); + assertThat(service.canSupportPolicyType( + new ToscaPolicyTypeIdentifier("onap.policies.controlloop.guard.common.Filter", "1.0.0"))).isTrue(); } @Test @@ -352,6 +354,77 @@ public class GuardPdpApplicationTest { requestAndCheckDecision(requestVfCount, DENY); } + @SuppressWarnings("unchecked") + @Test + public void test6Filters() throws Exception { + LOGGER.info("**************** Running test6Filters ****************"); + // + // Re-Load Decision Request - so we can start from scratch + // + requestVfCount = + gson.decode(TextFileUtils.getTextFileAsString("src/test/resources/requests/guard.vfCount.json"), + DecisionRequest.class); + // + // Ensure we are a permit to start + // + requestAndCheckDecision(requestVfCount, PERMIT); + // + // Load the filter policy in with the others. + // + List loadedPolicies = + TestUtils.loadPolicies("src/test/resources/test.policy.guard.filters.yaml", service); + assertThat(loadedPolicies).hasSize(2); + // + // Although the region is blacklisted, the id is not + // + requestAndCheckDecision(requestVfCount, PERMIT); + // + // Put in a different vnf id + // + ((Map) requestVfCount.getResource().get("guard")).put("generic-vnf.vnf-id", + "different-vnf-id-should-be-denied"); + // + // The region is blacklisted, and the id is not allowed + // + requestAndCheckDecision(requestVfCount, DENY); + // + // Let's switch to a different region + // + ((Map) requestVfCount.getResource().get("guard")).put("cloud-region.cloud-region-id", + "RegionTwo"); + // + // The region is whitelisted, and the id is also allowed + // + requestAndCheckDecision(requestVfCount, PERMIT); + // + // Put in a blacklisted vnf id + // + ((Map) requestVfCount.getResource().get("guard")).put("generic-vnf.vnf-id", + "f17face5-69cb-4c88-9e0b-7426db7edddd"); + // + // Although region is whitelisted, the id is blacklisted + // + requestAndCheckDecision(requestVfCount, DENY); + // + // Let's switch to a different region + // + ((Map) requestVfCount.getResource().get("guard")).put("cloud-region.cloud-region-id", + "RegionThree"); + // + // There is no filter for this region, but the id is still blacklisted + // + requestAndCheckDecision(requestVfCount, DENY); + // + // Put in a different vnf id + // + ((Map) requestVfCount.getResource().get("guard")).put("generic-vnf.vnf-id", + "different-vnf-id-should-be-permitted"); + // + // There is no filter for this region, and the id is not blacklisted + // + requestAndCheckDecision(requestVfCount, PERMIT); + } + @SuppressWarnings("unchecked") private void insertOperationEvent(DecisionRequest request) { // diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java index 41fd4705..1c925ce2 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java @@ -28,6 +28,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.HashMap; import java.util.Map; import org.junit.Test; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.TextFileUtils; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; @@ -92,4 +94,22 @@ public class GuardPolicyRequestTest { GuardPolicyRequest.createInstance(decisionRequest)); } + @Test + public void testFilterResources() throws Exception { + StandardCoder gson = new StandardCoder(); + + DecisionRequest request = gson.decode( + TextFileUtils.getTextFileAsString("src/test/resources/requests/guard.filter.json"), + DecisionRequest.class); + + GuardPolicyRequest guardRequest = GuardPolicyRequest.createInstance(request); + + assertThat(guardRequest.getVnfName()).isEqualTo("my-name"); + assertThat(guardRequest.getVnfId()).isEqualTo("my-id"); + assertThat(guardRequest.getVnfType()).isEqualTo("my-type"); + assertThat(guardRequest.getVnfNfNamingCode()).isEqualTo("my-naming-code"); + assertThat(guardRequest.getVserverId()).isEqualTo("my-server-id"); + assertThat(guardRequest.getCloudRegionId()).isEqualTo("my-region"); + } + } diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java index 6f7edac4..07e60c61 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java @@ -115,6 +115,7 @@ public class GuardTranslatorTest { // for (Map policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { for (ToscaPolicy policy : policies.values()) { + LOGGER.info("Testing policy " + policy.getName()); if ("frequency-missing-properties".equals(policy.getName())) { assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> translator.convertPolicy(policy) @@ -135,6 +136,55 @@ public class GuardTranslatorTest { assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> translator.convertPolicy(policy) ).withMessageContaining("Missing blacklist"); + } else if ("blacklist-noalgorithm".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing precedence"); + } else if ("blacklist-badalgorithm".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class) + .isThrownBy(() -> translator.convertPolicy(policy)) + .withMessageContaining( + "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides"); + } else if ("filter-nofilter".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class) + .isThrownBy(() -> translator.convertPolicy(policy)) + .withMessageContaining("Missing filters"); + } else if ("filter-nocollection".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Filters is not a collection"); + } else if ("filter-noarray".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Filters is not a collection"); + } else if ("filter-missingfield".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing \'field\' from filter"); + } else if ("filter-badfield".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Unexpected value for field in filter"); + } else if ("filter-missingfilter".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing \'filter\' from filter"); + } else if ("filter-missingfunction".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing \'function\' from filter"); + } else if ("filter-badfunction".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Unexpected value for function in filter"); + } else if ("filter-missingblacklist".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing \'blacklist\' from filter"); + } else if ("filter-badblacklist".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Unexpected value for blacklist in filter"); } } } @@ -190,6 +240,8 @@ public class GuardTranslatorTest { validateMinMax(policy, xacmlPolicy); } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) { validateBlacklist(policy, xacmlPolicy); + } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) { + validateFilter(policy, xacmlPolicy); } } } @@ -322,4 +374,26 @@ public class GuardTranslatorTest { } assertThat(foundBlacklist).isTrue(); } + + private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) { + assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides"); + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + assertThat(((RuleType) rule).getTarget()).isNotNull(); + assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1); + for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + assertThat(allOf.getMatch()).hasSize(1); + for (MatchType match : allOf.getMatch()) { + assertThat(match.getAttributeDesignator().getAttributeId()) + .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID); + } + } + } + } + } } diff --git a/applications/guard/src/test/resources/requests/guard.filter.json b/applications/guard/src/test/resources/requests/guard.filter.json new file mode 100644 index 00000000..710cf659 --- /dev/null +++ b/applications/guard/src/test/resources/requests/guard.filter.json @@ -0,0 +1,22 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-1", + "action": "guard", + "resource": { + "guard": { + "actor": "SO", + "operation": "VF Module Create", + "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", + "target": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e", + "vfCount": "0", + "generic-vnf.vnf-name": "my-name", + "generic-vnf.vnf-id": "my-id", + "generic-vnf.vnf-type": "my-type", + "generic-vnf.nf-naming-code": "my-naming-code", + "vserver.vserver-id": "my-server-id", + "cloud-region.cloud-region-id": "my-region" + } + } +} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.json b/applications/guard/src/test/resources/requests/guard.vfCount.json index 1a0a6e55..86a0a963 100644 --- a/applications/guard/src/test/resources/requests/guard.vfCount.json +++ b/applications/guard/src/test/resources/requests/guard.vfCount.json @@ -10,7 +10,13 @@ "operation": "VF Module Create", "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", "target": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e", - "vfCount": "0" + "vfCount": "0", + "generic-vnf.vnf-name": "Ete_vFWCLvFWSNK_7ba1fbde_0", + "generic-vnf.vnf-id": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e", + "generic-vnf.vnf-type": "vFWCL 2019-05-01 15:30:/vFWCL_vFWSNK bbefb8ce-2bde 0", + "generic-vnf.nf-naming-code": "aabbccddee", + "vserver.vserver-id": "e591441a-e649-4490-82e0-07dac05d674b", + "cloud-region.cloud-region-id": "RegionOne" } } } diff --git a/applications/guard/src/test/resources/test-bad-policies.yaml b/applications/guard/src/test/resources/test-bad-policies.yaml index df2431d4..07040c54 100644 --- a/applications/guard/src/test/resources/test-bad-policies.yaml +++ b/applications/guard/src/test/resources/test-bad-policies.yaml @@ -1,35 +1,126 @@ tosca_definitions_version: tosca_simple_yaml_1_1_0 topology_template: - policies: - - - frequency-missing-properties: - type: onap.policies.controlloop.guard.common.FrequencyLimiter - type_version: 1.0.0 - version: 1.0.0 - - - frequency-timewindow: - type: onap.policies.controlloop.guard.common.FrequencyLimiter - type_version: 1.0.0 - version: 1.0.0 - properties: + policies: + - frequency-missing-properties: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + - frequency-timewindow: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + properties: limit: 5 timeWindow: i am a bad value - - - minmax-notarget: - type: onap.policies.controlloop.guard.common.MinMax - type_version: 1.0.0 - version: 1.0.0 - properties: - - - minmax-nominmax: - type: onap.policies.controlloop.guard.common.MinMax - type_version: 1.0.0 - version: 1.0.0 - properties: + - minmax-notarget: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: null + - minmax-nominmax: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: target: foo - - - blacklist-noblacklist: - type: onap.policies.controlloop.guard.common.Blacklist - type_version: 1.0.0 - version: 1.0.0 - properties: + - blacklist-noblacklist: + type: onap.policies.controlloop.guard.common.Blacklist + type_version: 1.0.0 + version: 1.0.0 + properties: null + - filter-noalgorithm: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: null + - filter-badalgorithm: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: idontknow + - filter-nofilter: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: whitelist-overrides + - filter-nocollection: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: vnf1 + - filter-noarray: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + field: geo + - filter-missingfield: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - filter: foo + - filter-badfield: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: notinaai + - filter-missingfilter: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: generic-vnf.vnf-name + - filter-missingfunction: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: generic-vnf.vnf-name + filter: vfwl* + - filter-badfunction: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: generic-vnf.vnf-name + filter: vfwl* + function: notafunction + - filter-missingblacklist: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: generic-vnf.vnf-name + filter: vfwl* + function: string-equal + - filter-badblacklist: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + algorithm: blacklist-overrides + filters: + - field: generic-vnf.vnf-name + filter: vfwl* + function: string-equal + blacklist: shouldbeboolean \ No newline at end of file diff --git a/applications/guard/src/test/resources/test-policies.yaml b/applications/guard/src/test/resources/test-policies.yaml index 1ac7271c..e33f116a 100644 --- a/applications/guard/src/test/resources/test-policies.yaml +++ b/applications/guard/src/test/resources/test-policies.yaml @@ -99,6 +99,60 @@ topology_template: blacklist: - vnf1 - vnf2 + - + filter-1: + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : filter-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: "*" + id: loop-1 + algorithm: blacklist-overrides + filters: + - field: "generic-vnf.vnf-id" + function: "string-equal" + filter: "vf-module-id-2" + blacklist: true + - field: "generic-vnf.vnf-name" + function: "string-equal-ignore-case" + filter: "vf-MODULE-id-2" + blacklist: true + - field: "generic-vnf.vnf-type" + function: "string-starts-with" + filter: "vf-module" + blacklist: true + - field: "generic-vnf.nf-naming-code" + function: "string-regexp-match" + filter: "[0-9][a-zA-Z]+" + blacklist: true + - field: "vserver.vserver-id" + function: "string-contains" + filter: "myserver" + blacklist: true + - field: "cloud-region.cloud-region-id" + function: "string-ends-with" + filter: "mycloud" + blacklist: false + - field: "cloud-region.cloud-region-id" + function: "string-greater-than" + filter: "00" + blacklist: false + - field: "cloud-region.cloud-region-id" + function: "string-greater-than-or-equal" + filter: "00" + blacklist: false + - field: "cloud-region.cloud-region-id" + function: "string-less-than" + filter: "99" + blacklist: false + - field: "cloud-region.cloud-region-id" + function: "string-less-than-or-equal" + filter: "99" + blacklist: false - unknown-1: type: onap.policies.controlloop.guard.common.Unknown diff --git a/applications/guard/src/test/resources/test.policy.guard.filters.yaml b/applications/guard/src/test/resources/test.policy.guard.filters.yaml new file mode 100644 index 00000000..261ffbee --- /dev/null +++ b/applications/guard/src/test/resources/test.policy.guard.filters.yaml @@ -0,0 +1,39 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - filter.block.region.allow.one.vnf: + description: Block this region from Control Loop actions, but allow a specific vnf. + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + algorithm: whitelist-overrides + filters: + - field: cloud-region.cloud-region-id + filter: RegionOne + function: string-equal + blacklist: true + - field: generic-vnf.vnf-id + filter: e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e + function: string-equal + blacklist: false + - filter.allow.region.block.one.vnf: + description: allow this region to do Control Loop actions, but block a specific vnf. + type: onap.policies.controlloop.guard.common.Filter + type_version: 1.0.0 + version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + algorithm: blacklist-overrides + filters: + - field: cloud-region.cloud-region-id + filter: RegionTwo + function: string-equal + blacklist: false + - field: generic-vnf.vnf-id + filter: f17face5-69cb-4c88-9e0b-7426db7edddd + function: string-equal + blacklist: true \ No newline at end of file diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManagerTest.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManagerTest.java index 2a85579c..cd7041ed 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManagerTest.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManagerTest.java @@ -142,10 +142,10 @@ public class XacmlPdpApplicationManagerTest { // assertThat(manager).isNotNull(); assertThat(manager.getPolicyCount()).isZero(); - assertThat(manager.getPolicyTypeCount()).isEqualTo(19); + assertThat(manager.getPolicyTypeCount()).isEqualTo(20); assertThat(manager.getToscaPolicies()).isEmpty(); assertThat(manager.getToscaPolicyIdentifiers()).isEmpty(); - assertThat(manager.getToscaPolicyTypeIdents()).hasSize(19); + assertThat(manager.getToscaPolicyTypeIdents()).hasSize(20); assertThat(manager.findNativeApplication()).isInstanceOf(NativePdpApplication.class); -- 2.16.6