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 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.std.StdMutableResponse;
32 import com.att.research.xacml.std.StdMutableResult;
33 import com.att.research.xacml.std.StdStatus;
34 import com.att.research.xacml.std.StdStatusCode;
35 import com.att.research.xacml.util.XACMLPolicyWriter;
36 import java.io.ByteArrayOutputStream;
37 import java.util.HashMap;
38 import java.util.LinkedHashMap;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
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("frequency-badtimerange_start", "Invalid timeRange");
123 name2message.put("frequency-badtimerange_end", "Invalid timeRange");
124 name2message.put("frequency-badtimerange_value", "timestamp 99:99:99 could not be parsed");
125 name2message.put("minmax-notarget", "Missing target field in minmax policy");
126 name2message.put("minmax-nominmax", "Missing min or max field in minmax policy");
127 name2message.put("blacklist-noblacklist", "Missing blacklist");
128 name2message.put("filter-noalgorithm", "Missing algorithm");
129 name2message.put("filter-badalgorithm",
130 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
131 name2message.put("filter-nofilter", "Missing filters");
132 name2message.put("filter-nocollection", "Filters is not a collection");
133 name2message.put("filter-noarray", "Filters is not a collection");
134 name2message.put("filter-missingfield", "Missing \'field\' from filter");
135 name2message.put("filter-badfield", "Unexpected value for field in filter");
136 name2message.put("filter-missingfilter", "Missing \'filter\' from filter");
137 name2message.put("filter-missingfunction", "Missing \'function\' from filter");
138 name2message.put("filter-badfunction", "Unexpected value for function in filter");
139 name2message.put("filter-missingblacklist", "Missing \'blacklist\' from filter");
140 name2message.put("filter-badblacklist", "Unexpected value for blacklist in filter");
144 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
145 for (ToscaPolicy policy : policies.values()) {
146 LOGGER.info("Testing policy " + policy.getName());
147 String expectedMsg = name2message.get(policy.getName());
148 assertThat(expectedMsg).as(policy.getName()).isNotNull();
150 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
151 translator.convertPolicy(policy)
152 ).withMessageContaining(expectedMsg);
158 public void testPolicyConversion() throws Exception {
159 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
161 // Serialize it into a class
163 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
165 // Make sure all the fields are setup properly
167 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
168 jtst.fromAuthorative(serviceTemplate);
169 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
173 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
174 for (ToscaPolicy policy : policies.values()) {
176 // Convert the policy
178 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
179 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
180 translator.convertPolicy(policy));
183 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
184 assertThat(xacmlPolicy).isNotNull();
188 ByteArrayOutputStream os = new ByteArrayOutputStream();
189 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
190 LOGGER.info(os.toString());
192 // Validate the policy
194 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
195 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
196 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
197 validateCommon(policy, xacmlPolicy);
199 // Validate each policy type
201 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
202 validateFrequency(policy, xacmlPolicy);
203 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
204 validateMinMax(policy, xacmlPolicy);
205 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
206 validateBlacklist(policy, xacmlPolicy);
207 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
208 validateFilter(policy, xacmlPolicy);
213 ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
215 testPol.setProperties(new LinkedHashMap<>());
216 assertThatExceptionOfType(ToscaPolicyConversionException.class)
217 .isThrownBy(() -> translator.convertPolicy(testPol));
219 testPol.setProperties(null);
220 assertThatExceptionOfType(ToscaPolicyConversionException.class)
221 .isThrownBy(() -> translator.convertPolicy(testPol));
224 private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
225 boolean foundActor = false;
226 boolean foundOperation = false;
227 boolean foundTarget = false;
228 boolean foundControlLoop = false;
229 //boolean foundTimeRange = false;
231 assertThat(xacmlPolicy.getTarget()).isNotNull();
232 assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
233 for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
234 assertThat(anyOf.getAllOf()).isNotEmpty();
235 for (AllOfType allOf : anyOf.getAllOf()) {
236 assertThat(allOf.getMatch()).isNotEmpty();
237 for (MatchType match : allOf.getMatch()) {
239 // These fields are required
241 if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
242 match.getAttributeDesignator().getAttributeId())) {
243 assertThat(match.getAttributeValue().getContent()).isNotNull();
245 } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
246 match.getAttributeDesignator().getAttributeId())) {
247 assertThat(match.getAttributeValue().getContent()).isNotNull();
248 foundOperation = true;
251 // These fields are optional
253 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
254 match.getAttributeDesignator().getAttributeId())) {
255 assertThat(policy.getProperties()).containsKey("target");
258 if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
259 match.getAttributeDesignator().getAttributeId())) {
260 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
261 foundControlLoop = true;
264 if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
265 match.getAttributeDesignator().getAttributeId())) {
266 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
267 foundTimeRange = true;
274 assertThat(foundActor && foundOperation).isTrue();
275 if (policy.getProperties().containsKey("target")) {
276 assertThat(foundTarget).isTrue();
278 if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
279 assertThat(foundControlLoop).isTrue();
281 if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
282 assertThat(xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition())
283 .hasAtLeastOneElementOfType(VariableDefinitionType.class);
287 private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
288 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
289 if (! (rule instanceof RuleType)) {
292 assertThat(((RuleType) rule).getCondition()).isNotNull();
293 assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
297 private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
298 boolean foundTarget = false;
299 boolean foundMinOrMax = false;
300 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
301 if (! (rule instanceof RuleType)) {
304 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
305 assertThat(anyOf.getAllOf()).isNotEmpty();
306 for (AllOfType allOf : anyOf.getAllOf()) {
307 assertThat(allOf.getMatch()).isNotEmpty();
308 for (MatchType match : allOf.getMatch()) {
309 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
310 match.getAttributeDesignator().getAttributeId())) {
311 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
313 } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
314 match.getAttributeDesignator().getAttributeId())) {
315 assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
316 GuardTranslator.FIELD_MAX);
317 foundMinOrMax = true;
323 assertThat(foundTarget && foundMinOrMax).isTrue();
326 private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
327 boolean foundBlacklist = false;
328 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
329 if (! (rule instanceof RuleType)) {
332 assertThat(((RuleType) rule).getTarget()).isNotNull();
333 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
334 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
335 assertThat(anyOf.getAllOf()).isNotEmpty();
336 for (AllOfType allOf : anyOf.getAllOf()) {
337 assertThat(allOf.getMatch()).isNotEmpty();
338 assertThat(allOf.getMatch()).hasSize(1);
339 for (MatchType match : allOf.getMatch()) {
340 assertThat(match.getAttributeDesignator().getAttributeId())
341 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
342 assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
344 // This just checks that policy did have a blacklist in it.
346 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
347 foundBlacklist = true;
352 assertThat(foundBlacklist).isTrue();
355 private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
356 assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
357 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
358 if (! (rule instanceof RuleType)) {
361 assertThat(((RuleType) rule).getTarget()).isNotNull();
362 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
363 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
364 assertThat(anyOf.getAllOf()).isNotEmpty();
365 for (AllOfType allOf : anyOf.getAllOf()) {
366 assertThat(allOf.getMatch()).isNotEmpty();
367 assertThat(allOf.getMatch()).hasSize(1);
368 for (MatchType match : allOf.getMatch()) {
369 assertThat(match.getAttributeDesignator().getAttributeId())
370 .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);