2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 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 static org.assertj.core.api.Assertions.assertThat;
27 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
29 import com.att.research.xacml.api.Decision;
30 import com.att.research.xacml.api.Request;
31 import com.att.research.xacml.api.XACML3;
32 import com.att.research.xacml.std.StdMutableResponse;
33 import com.att.research.xacml.std.StdMutableResult;
34 import com.att.research.xacml.std.StdStatus;
35 import com.att.research.xacml.std.StdStatusCode;
36 import com.att.research.xacml.util.XACMLPolicyWriter;
37 import java.io.ByteArrayOutputStream;
38 import java.util.HashMap;
39 import java.util.LinkedHashMap;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
46 import org.junit.Test;
47 import org.onap.policy.common.utils.coder.StandardCoder;
48 import org.onap.policy.common.utils.coder.StandardYamlCoder;
49 import org.onap.policy.common.utils.resources.ResourceUtils;
50 import org.onap.policy.common.utils.resources.TextFileUtils;
51 import org.onap.policy.models.decisions.concepts.DecisionRequest;
52 import org.onap.policy.models.decisions.concepts.DecisionResponse;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
54 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
55 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
56 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
57 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 public class GuardTranslatorTest {
62 private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class);
63 private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
64 private static StandardCoder gson = new StandardCoder();
66 private GuardTranslator translator = new GuardTranslator();
69 public void testRequest() throws Exception {
70 DecisionRequest decisionRequest = gson.decode(
71 TextFileUtils.getTextFileAsString(
72 "src/test/resources/requests/guard.vfCount.json"),
73 DecisionRequest.class);
74 Request xacmlRequest = translator.convertRequest(decisionRequest);
76 assertThat(xacmlRequest).isNotNull();
80 public void testResponse() {
81 StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK);
82 StdMutableResult result = new StdMutableResult(Decision.PERMIT, status);
83 StdMutableResponse response = new StdMutableResponse(result);
85 DecisionResponse decisionResponse = translator.convertResponse(response);
86 assertThat(decisionResponse).isNotNull();
87 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
89 result = new StdMutableResult(Decision.DENY, status);
90 response = new StdMutableResponse(result);
91 decisionResponse = translator.convertResponse(response);
92 assertThat(decisionResponse).isNotNull();
93 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString());
95 result = new StdMutableResult(Decision.INDETERMINATE, status);
96 response = new StdMutableResponse(result);
97 decisionResponse = translator.convertResponse(response);
98 assertThat(decisionResponse).isNotNull();
99 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
104 public void testBadPolicies() throws Exception {
105 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
107 // Serialize it into a class
109 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
111 // Make sure all the fields are setup properly
113 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
114 jtst.fromAuthorative(serviceTemplate);
115 final ToscaServiceTemplate completedJtst = jtst.toAuthorative();
117 // Expected message for given policy name
119 final Map<String, String> name2message = new HashMap<>();
120 name2message.put("frequency-missing-properties", "Missing property limit");
121 name2message.put("frequency-timewindow", "timeWindow is not an integer");
122 name2message.put("minmax-notarget", "Missing target field in minmax policy");
123 name2message.put("minmax-nominmax", "Missing min or max field in minmax policy");
124 name2message.put("blacklist-noblacklist", "Missing blacklist");
125 name2message.put("filter-noalgorithm", "Missing algorithm");
126 name2message.put("filter-badalgorithm",
127 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
128 name2message.put("filter-nofilter", "Missing filters");
129 name2message.put("filter-nocollection", "Filters is not a collection");
130 name2message.put("filter-noarray", "Filters is not a collection");
131 name2message.put("filter-missingfield", "Missing \'field\' from filter");
132 name2message.put("filter-badfield", "Unexpected value for field in filter");
133 name2message.put("filter-missingfilter", "Missing \'filter\' from filter");
134 name2message.put("filter-missingfunction", "Missing \'function\' from filter");
135 name2message.put("filter-badfunction", "Unexpected value for function in filter");
136 name2message.put("filter-missingblacklist", "Missing \'blacklist\' from filter");
137 name2message.put("filter-badblacklist", "Unexpected value for blacklist in filter");
141 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
142 for (ToscaPolicy policy : policies.values()) {
143 LOGGER.info("Testing policy " + policy.getName());
144 String expectedMsg = name2message.get(policy.getName());
145 assertThat(expectedMsg).as(policy.getName()).isNotNull();
147 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
148 translator.convertPolicy(policy)
149 ).withMessageContaining(expectedMsg);
155 public void testPolicyConversion() throws Exception {
156 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
158 // Serialize it into a class
160 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
162 // Make sure all the fields are setup properly
164 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
165 jtst.fromAuthorative(serviceTemplate);
166 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
170 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
171 for (ToscaPolicy policy : policies.values()) {
173 // Convert the policy
175 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
176 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
177 translator.convertPolicy(policy));
180 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
181 assertThat(xacmlPolicy).isNotNull();
185 ByteArrayOutputStream os = new ByteArrayOutputStream();
186 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
187 LOGGER.info(os.toString());
189 // Validate the policy
191 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
192 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
193 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
194 validateCommon(policy, xacmlPolicy);
196 // Validate each policy type
198 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
199 validateFrequency(policy, xacmlPolicy);
200 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
201 validateMinMax(policy, xacmlPolicy);
202 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
203 validateBlacklist(policy, xacmlPolicy);
204 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
205 validateFilter(policy, xacmlPolicy);
210 ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
212 testPol.setProperties(new LinkedHashMap<>());
213 assertThatExceptionOfType(ToscaPolicyConversionException.class)
214 .isThrownBy(() -> translator.convertPolicy(testPol));
216 testPol.setProperties(null);
217 assertThatExceptionOfType(ToscaPolicyConversionException.class)
218 .isThrownBy(() -> translator.convertPolicy(testPol));
221 private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
222 boolean foundActor = false;
223 boolean foundOperation = false;
224 boolean foundTarget = false;
225 boolean foundControlLoop = false;
226 boolean foundTimeRange = false;
228 assertThat(xacmlPolicy.getTarget()).isNotNull();
229 assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
230 for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
231 assertThat(anyOf.getAllOf()).isNotEmpty();
232 for (AllOfType allOf : anyOf.getAllOf()) {
233 assertThat(allOf.getMatch()).isNotEmpty();
234 for (MatchType match : allOf.getMatch()) {
236 // These fields are required
238 if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
239 match.getAttributeDesignator().getAttributeId())) {
240 assertThat(match.getAttributeValue().getContent()).isNotNull();
242 } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
243 match.getAttributeDesignator().getAttributeId())) {
244 assertThat(match.getAttributeValue().getContent()).isNotNull();
245 foundOperation = true;
248 // These fields are optional
250 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
251 match.getAttributeDesignator().getAttributeId())) {
252 assertThat(policy.getProperties()).containsKey("target");
255 if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
256 match.getAttributeDesignator().getAttributeId())) {
257 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
258 foundControlLoop = true;
260 if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
261 match.getAttributeDesignator().getAttributeId())) {
262 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
263 foundTimeRange = true;
269 assertThat(foundActor && foundOperation).isTrue();
270 if (policy.getProperties().containsKey("target")) {
271 assertThat(foundTarget).isTrue();
273 if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
274 assertThat(foundControlLoop).isTrue();
276 if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
277 assertThat(foundTimeRange).isTrue();
281 private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
282 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
283 if (! (rule instanceof RuleType)) {
286 assertThat(((RuleType) rule).getCondition()).isNotNull();
287 assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
291 private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
292 boolean foundTarget = false;
293 boolean foundMinOrMax = false;
294 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
295 if (! (rule instanceof RuleType)) {
298 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
299 assertThat(anyOf.getAllOf()).isNotEmpty();
300 for (AllOfType allOf : anyOf.getAllOf()) {
301 assertThat(allOf.getMatch()).isNotEmpty();
302 for (MatchType match : allOf.getMatch()) {
303 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
304 match.getAttributeDesignator().getAttributeId())) {
305 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
307 } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
308 match.getAttributeDesignator().getAttributeId())) {
309 assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
310 GuardTranslator.FIELD_MAX);
311 foundMinOrMax = true;
317 assertThat(foundTarget && foundMinOrMax).isTrue();
320 private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
321 boolean foundBlacklist = false;
322 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
323 if (! (rule instanceof RuleType)) {
326 assertThat(((RuleType) rule).getTarget()).isNotNull();
327 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
328 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
329 assertThat(anyOf.getAllOf()).isNotEmpty();
330 for (AllOfType allOf : anyOf.getAllOf()) {
331 assertThat(allOf.getMatch()).isNotEmpty();
332 assertThat(allOf.getMatch()).hasSize(1);
333 for (MatchType match : allOf.getMatch()) {
334 assertThat(match.getAttributeDesignator().getAttributeId())
335 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
336 assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
338 // This just checks that policy did have a blacklist in it.
340 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
341 foundBlacklist = true;
346 assertThat(foundBlacklist).isTrue();
349 private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
350 assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
351 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
352 if (! (rule instanceof RuleType)) {
355 assertThat(((RuleType) rule).getTarget()).isNotNull();
356 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
357 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
358 assertThat(anyOf.getAllOf()).isNotEmpty();
359 for (AllOfType allOf : anyOf.getAllOf()) {
360 assertThat(allOf.getMatch()).isNotEmpty();
361 assertThat(allOf.getMatch()).hasSize(1);
362 for (MatchType match : allOf.getMatch()) {
363 assertThat(match.getAttributeDesignator().getAttributeId())
364 .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);