2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.xacml.pdp.application.guard;
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
28 import com.att.research.xacml.api.Decision;
29 import com.att.research.xacml.api.Request;
30 import com.att.research.xacml.api.XACML3;
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;
38 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
43 import org.junit.Test;
44 import org.onap.policy.common.utils.coder.StandardCoder;
45 import org.onap.policy.common.utils.coder.StandardYamlCoder;
46 import org.onap.policy.common.utils.resources.ResourceUtils;
47 import org.onap.policy.common.utils.resources.TextFileUtils;
48 import org.onap.policy.models.decisions.concepts.DecisionRequest;
49 import org.onap.policy.models.decisions.concepts.DecisionResponse;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
52 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
53 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
54 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 public class GuardTranslatorTest {
59 private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class);
60 private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
61 private static StandardCoder gson = new StandardCoder();
63 private GuardTranslator translator = new GuardTranslator();
66 public void testRequest() throws Exception {
67 DecisionRequest decisionRequest = gson.decode(
68 TextFileUtils.getTextFileAsString(
69 "src/test/resources/requests/guard.vfCount.json"),
70 DecisionRequest.class);
71 Request xacmlRequest = translator.convertRequest(decisionRequest);
73 assertThat(xacmlRequest).isNotNull();
77 public void testResponse() {
78 StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK);
79 StdMutableResult result = new StdMutableResult(Decision.PERMIT, status);
80 StdMutableResponse response = new StdMutableResponse(result);
82 DecisionResponse decisionResponse = translator.convertResponse(response);
83 assertThat(decisionResponse).isNotNull();
84 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
86 result = new StdMutableResult(Decision.DENY, status);
87 response = new StdMutableResponse(result);
88 decisionResponse = translator.convertResponse(response);
89 assertThat(decisionResponse).isNotNull();
90 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString());
92 result = new StdMutableResult(Decision.INDETERMINATE, status);
93 response = new StdMutableResponse(result);
94 decisionResponse = translator.convertResponse(response);
95 assertThat(decisionResponse).isNotNull();
96 assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
101 public void testBadPolicies() throws Exception {
102 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
104 // Serialize it into a class
106 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
108 // Make sure all the fields are setup properly
110 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
111 jtst.fromAuthorative(serviceTemplate);
112 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
116 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
117 for (ToscaPolicy policy : policies.values()) {
118 LOGGER.info("Testing policy " + policy.getName());
119 if ("frequency-missing-properties".equals(policy.getName())) {
120 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
121 translator.convertPolicy(policy)
122 ).withMessageContaining("Missing property limit");
123 } else if ("frequency-timewindow".equals(policy.getName())) {
124 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
125 translator.convertPolicy(policy)
126 ).withMessageContaining("timeWindow is not an integer");
127 } else if ("minmax-notarget".equals(policy.getName())) {
128 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
129 translator.convertPolicy(policy)
130 ).withMessageContaining("Missing target field in minmax policy");
131 } else if ("minmax-nominmax".equals(policy.getName())) {
132 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
133 translator.convertPolicy(policy)
134 ).withMessageContaining("Missing min or max field in minmax policy");
135 } else if ("blacklist-noblacklist".equals(policy.getName())) {
136 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
137 translator.convertPolicy(policy)
138 ).withMessageContaining("Missing blacklist");
139 } else if ("filter-noalgorithm".equals(policy.getName())) {
140 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
141 translator.convertPolicy(policy)
142 ).withMessageContaining("Missing algorithm");
143 } else if ("filter-badalgorithm".equals(policy.getName())) {
144 assertThatExceptionOfType(ToscaPolicyConversionException.class)
145 .isThrownBy(() -> translator.convertPolicy(policy))
146 .withMessageContaining(
147 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
148 } else if ("filter-nofilter".equals(policy.getName())) {
149 assertThatExceptionOfType(ToscaPolicyConversionException.class)
150 .isThrownBy(() -> translator.convertPolicy(policy))
151 .withMessageContaining("Missing filters");
152 } else if ("filter-nocollection".equals(policy.getName())) {
153 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
154 translator.convertPolicy(policy)
155 ).withMessageContaining("Filters is not a collection");
156 } else if ("filter-noarray".equals(policy.getName())) {
157 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
158 translator.convertPolicy(policy)
159 ).withMessageContaining("Filters is not a collection");
160 } else if ("filter-missingfield".equals(policy.getName())) {
161 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
162 translator.convertPolicy(policy)
163 ).withMessageContaining("Missing \'field\' from filter");
164 } else if ("filter-badfield".equals(policy.getName())) {
165 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
166 translator.convertPolicy(policy)
167 ).withMessageContaining("Unexpected value for field in filter");
168 } else if ("filter-missingfilter".equals(policy.getName())) {
169 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
170 translator.convertPolicy(policy)
171 ).withMessageContaining("Missing \'filter\' from filter");
172 } else if ("filter-missingfunction".equals(policy.getName())) {
173 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
174 translator.convertPolicy(policy)
175 ).withMessageContaining("Missing \'function\' from filter");
176 } else if ("filter-badfunction".equals(policy.getName())) {
177 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
178 translator.convertPolicy(policy)
179 ).withMessageContaining("Unexpected value for function in filter");
180 } else if ("filter-missingblacklist".equals(policy.getName())) {
181 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
182 translator.convertPolicy(policy)
183 ).withMessageContaining("Missing \'blacklist\' from filter");
184 } else if ("filter-badblacklist".equals(policy.getName())) {
185 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
186 translator.convertPolicy(policy)
187 ).withMessageContaining("Unexpected value for blacklist in filter");
194 public void testPolicyConversion() throws Exception {
195 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
197 // Serialize it into a class
199 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
201 // Make sure all the fields are setup properly
203 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
204 jtst.fromAuthorative(serviceTemplate);
205 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
209 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
210 for (ToscaPolicy policy : policies.values()) {
212 // Convert the policy
214 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
215 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
216 translator.convertPolicy(policy));
219 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
220 assertThat(xacmlPolicy).isNotNull();
224 ByteArrayOutputStream os = new ByteArrayOutputStream();
225 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
226 LOGGER.info(os.toString());
228 // Validate the policy
230 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
231 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
232 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
233 validateCommon(policy, xacmlPolicy);
235 // Validate each policy type
237 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
238 validateFrequency(policy, xacmlPolicy);
239 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
240 validateMinMax(policy, xacmlPolicy);
241 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
242 validateBlacklist(policy, xacmlPolicy);
243 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
244 validateFilter(policy, xacmlPolicy);
250 private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
251 boolean foundActor = false;
252 boolean foundOperation = false;
253 boolean foundTarget = false;
254 boolean foundControlLoop = false;
255 boolean foundTimeRange = false;
257 assertThat(xacmlPolicy.getTarget()).isNotNull();
258 assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
259 for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
260 assertThat(anyOf.getAllOf()).isNotEmpty();
261 for (AllOfType allOf : anyOf.getAllOf()) {
262 assertThat(allOf.getMatch()).isNotEmpty();
263 for (MatchType match : allOf.getMatch()) {
265 // These fields are required
267 if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
268 match.getAttributeDesignator().getAttributeId())) {
269 assertThat(match.getAttributeValue().getContent()).isNotNull();
271 } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
272 match.getAttributeDesignator().getAttributeId())) {
273 assertThat(match.getAttributeValue().getContent()).isNotNull();
274 foundOperation = true;
277 // These fields are optional
279 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
280 match.getAttributeDesignator().getAttributeId())) {
281 assertThat(policy.getProperties()).containsKey("target");
284 if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
285 match.getAttributeDesignator().getAttributeId())) {
286 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
287 foundControlLoop = true;
289 if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
290 match.getAttributeDesignator().getAttributeId())) {
291 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
292 foundTimeRange = true;
298 assertThat(foundActor && foundOperation).isTrue();
299 if (policy.getProperties().containsKey("target")) {
300 assertThat(foundTarget).isTrue();
302 if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
303 assertThat(foundControlLoop).isTrue();
305 if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
306 assertThat(foundTimeRange).isTrue();
310 private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
311 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
312 if (! (rule instanceof RuleType)) {
315 assertThat(((RuleType) rule).getCondition()).isNotNull();
316 assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
320 private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
321 boolean foundTarget = false;
322 boolean foundMinOrMax = false;
323 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
324 if (! (rule instanceof RuleType)) {
327 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
328 assertThat(anyOf.getAllOf()).isNotEmpty();
329 for (AllOfType allOf : anyOf.getAllOf()) {
330 assertThat(allOf.getMatch()).isNotEmpty();
331 for (MatchType match : allOf.getMatch()) {
332 if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
333 match.getAttributeDesignator().getAttributeId())) {
334 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
336 } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
337 match.getAttributeDesignator().getAttributeId())) {
338 assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
339 GuardTranslator.FIELD_MAX);
340 foundMinOrMax = true;
346 assertThat(foundTarget && foundMinOrMax).isTrue();
349 private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
350 boolean foundBlacklist = false;
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 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
365 assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
367 // This just checks that policy did have a blacklist in it.
369 assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
370 foundBlacklist = true;
375 assertThat(foundBlacklist).isTrue();
378 private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
379 assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
380 for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
381 if (! (rule instanceof RuleType)) {
384 assertThat(((RuleType) rule).getTarget()).isNotNull();
385 assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
386 for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
387 assertThat(anyOf.getAllOf()).isNotEmpty();
388 for (AllOfType allOf : anyOf.getAllOf()) {
389 assertThat(allOf.getMatch()).isNotEmpty();
390 assertThat(allOf.getMatch()).hasSize(1);
391 for (MatchType match : allOf.getMatch()) {
392 assertThat(match.getAttributeDesignator().getAttributeId())
393 .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);