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", "item \"limit\"");
121 name2message.put("frequency-timewindow", "Cannot decode FrequencyDefinition");
122 name2message.put("frequency-badtimerange_start", "item \"startTime\"");
123 name2message.put("frequency-badtimerange_end", "item \"endTime\"");
124 name2message.put("frequency-badtimerange_value", "timestamp 99:99:99 could not be parsed");
125 name2message.put("minmax-notarget", "item \"target\"");
126 name2message.put("minmax-nominmax", "Missing min or max field in minmax policy");
127 name2message.put("blacklist-noblacklist", "item \"blacklist\"");
128 name2message.put("filter-noalgorithm", "item \"algorithm\"");
129 name2message.put("filter-badalgorithm",
130 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
131 name2message.put("filter-nofilter", "item \"filters\"");
132 name2message.put("filter-nocollection", "Cannot decode FilterDefinition");
133 name2message.put("filter-noarray", "Cannot decode FilterDefinition");
134 name2message.put("filter-missingfield", "item \"field\"");
135 name2message.put("filter-badfield", "Unexpected value for field in filter");
136 name2message.put("filter-missingfilter", "item \"filter\"");
137 name2message.put("filter-missingfunction", "item \"function\"");
138 name2message.put("filter-badfunction", "Unexpected value for function in filter");
139 name2message.put("filter-missingblacklist", "item \"blacklist\"");
143 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
144 for (ToscaPolicy policy : policies.values()) {
145 LOGGER.info("Testing policy " + policy.getName());
146 String expectedMsg = name2message.get(policy.getName());
147 assertThat(expectedMsg).as(policy.getName()).isNotNull();
149 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
150 translator.convertPolicy(policy)
151 ).as(policy.getName()).withMessageContaining(expectedMsg);
157 public void testPolicyConversion() throws Exception {
158 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
160 // Serialize it into a class
162 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
164 // Make sure all the fields are setup properly
166 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
167 jtst.fromAuthorative(serviceTemplate);
168 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
172 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
173 for (ToscaPolicy policy : policies.values()) {
175 // Convert the policy
177 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
178 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
179 translator.convertPolicy(policy));
182 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
183 assertThat(xacmlPolicy).isNotNull();
187 ByteArrayOutputStream os = new ByteArrayOutputStream();
188 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
189 LOGGER.info(os.toString());
191 // Validate the policy
193 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
194 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
195 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
196 validateCommon(policy, xacmlPolicy);
198 // Validate each policy type
200 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
201 validateFrequency(policy, xacmlPolicy);
202 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
203 validateMinMax(policy, xacmlPolicy);
204 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
205 validateBlacklist(policy, xacmlPolicy);
206 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
207 validateFilter(policy, xacmlPolicy);
212 ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
214 testPol.setProperties(new LinkedHashMap<>());
215 assertThatExceptionOfType(ToscaPolicyConversionException.class)
216 .isThrownBy(() -> translator.convertPolicy(testPol));
218 testPol.setProperties(null);
219 assertThatExceptionOfType(ToscaPolicyConversionException.class)
220 .isThrownBy(() -> translator.convertPolicy(testPol));
223 private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
224 boolean foundActor = false;
225 boolean foundOperation = false;
226 boolean foundTarget = false;
227 boolean foundControlLoop = false;
228 //boolean foundTimeRange = false;
230 assertThat(xacmlPolicy.getTarget()).isNotNull();
231 assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
232 for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
233 assertThat(anyOf.getAllOf()).isNotEmpty();
234 for (AllOfType allOf : anyOf.getAllOf()) {
235 assertThat(allOf.getMatch()).isNotEmpty();
236 for (MatchType match : allOf.getMatch()) {
238 // These fields are required
240 if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
241 match.getAttributeDesignator().getAttributeId())) {
242 assertThat(match.getAttributeValue().getContent()).isNotNull();
244 } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
245 match.getAttributeDesignator().getAttributeId())) {
246 assertThat(match.getAttributeValue().getContent()).isNotNull();
247 foundOperation = true;
250 // These fields are optional
252 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
253 match.getAttributeDesignator().getAttributeId())) {
254 assertThat(policy.getProperties()).containsKey("target");
257 if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
258 match.getAttributeDesignator().getAttributeId())) {
259 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
260 foundControlLoop = true;
263 if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
264 match.getAttributeDesignator().getAttributeId())) {
265 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
266 foundTimeRange = true;
273 assertThat(foundActor && foundOperation).isTrue();
274 if (policy.getProperties().containsKey("target")) {
275 assertThat(foundTarget).isTrue();
277 if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
278 assertThat(foundControlLoop).isTrue();
280 if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
281 assertThat(xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition())
282 .hasAtLeastOneElementOfType(VariableDefinitionType.class);
286 private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
287 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
288 if (! (rule instanceof RuleType)) {
291 assertThat(((RuleType) rule).getCondition()).isNotNull();
292 assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
296 private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
297 boolean foundTarget = false;
298 boolean foundMinOrMax = false;
299 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
300 if (! (rule instanceof RuleType)) {
303 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
304 assertThat(anyOf.getAllOf()).isNotEmpty();
305 for (AllOfType allOf : anyOf.getAllOf()) {
306 assertThat(allOf.getMatch()).isNotEmpty();
307 for (MatchType match : allOf.getMatch()) {
308 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
309 match.getAttributeDesignator().getAttributeId())) {
310 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
312 } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
313 match.getAttributeDesignator().getAttributeId())) {
314 assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
315 GuardTranslator.FIELD_MAX);
316 foundMinOrMax = true;
322 assertThat(foundTarget && foundMinOrMax).isTrue();
325 private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
326 boolean foundBlacklist = false;
327 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
328 if (! (rule instanceof RuleType)) {
331 assertThat(((RuleType) rule).getTarget()).isNotNull();
332 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
333 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
334 assertThat(anyOf.getAllOf()).isNotEmpty();
335 for (AllOfType allOf : anyOf.getAllOf()) {
336 assertThat(allOf.getMatch()).isNotEmpty();
337 assertThat(allOf.getMatch()).hasSize(1);
338 for (MatchType match : allOf.getMatch()) {
339 assertThat(match.getAttributeDesignator().getAttributeId())
340 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
341 assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
343 // This just checks that policy did have a blacklist in it.
345 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
346 foundBlacklist = true;
351 assertThat(foundBlacklist).isTrue();
354 private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
355 assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
356 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
357 if (! (rule instanceof RuleType)) {
360 assertThat(((RuleType) rule).getTarget()).isNotNull();
361 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
362 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
363 assertThat(anyOf.getAllOf()).isNotEmpty();
364 for (AllOfType allOf : anyOf.getAllOf()) {
365 assertThat(allOf.getMatch()).isNotEmpty();
366 assertThat(allOf.getMatch()).hasSize(1);
367 for (MatchType match : allOf.getMatch()) {
368 assertThat(match.getAttributeDesignator().getAttributeId())
369 .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);