Set all cross references of policy/xacml-pdp
[policy/xacml-pdp.git] / applications / guard / src / test / java / org / onap / policy / xacml / pdp / application / guard / GuardTranslatorTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  * SPDX-License-Identifier: Apache-2.0
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.policy.xacml.pdp.application.guard;
25
26 import static org.assertj.core.api.Assertions.assertThat;
27 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
28
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;
39 import java.util.Map;
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;
60
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();
65
66     private GuardTranslator translator = new GuardTranslator();
67
68     @Test
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);
75
76         assertThat(xacmlRequest).isNotNull();
77     }
78
79     @Test
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);
84
85         DecisionResponse decisionResponse = translator.convertResponse(response);
86         assertThat(decisionResponse).isNotNull();
87         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
88
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());
94
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());
100     }
101
102
103     @Test
104     public void testBadPolicies() throws Exception {
105         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
106         //
107         // Serialize it into a class
108         //
109         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
110         //
111         // Make sure all the fields are setup properly
112         //
113         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
114         jtst.fromAuthorative(serviceTemplate);
115         final ToscaServiceTemplate completedJtst = jtst.toAuthorative();
116         //
117         // Expected message for given policy name
118         //
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 \"start_time\"");
123         name2message.put("frequency-badtimerange_end", "item \"end_time\"");
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\"");
140         //
141         // Get the policies
142         //
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();
148
149                 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
150                     translator.convertPolicy(policy)
151                 ).as(policy.getName()).withMessageContaining(expectedMsg);
152             }
153         }
154     }
155
156     @Test
157     public void testPolicyConversion() throws Exception {
158         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
159         //
160         // Serialize it into a class
161         //
162         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
163         //
164         // Make sure all the fields are setup properly
165         //
166         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
167         jtst.fromAuthorative(serviceTemplate);
168         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
169         //
170         // Get the policies
171         //
172         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
173             for (ToscaPolicy policy : policies.values()) {
174                 //
175                 // Convert the policy
176                 //
177                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
178                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
179                         translator.convertPolicy(policy));
180                     continue;
181                 }
182                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
183                 assertThat(xacmlPolicy).isNotNull();
184                 //
185                 // Let's dump it out
186                 //
187                 ByteArrayOutputStream os = new ByteArrayOutputStream();
188                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
189                 LOGGER.info(os.toString());
190                 //
191                 // Validate the policy
192                 //
193                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
194                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
195                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
196                 validateCommon(policy, xacmlPolicy);
197                 //
198                 // Validate each policy type
199                 //
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);
208                 }
209             }
210         }
211
212         ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
213
214         testPol.setProperties(new LinkedHashMap<>());
215         assertThatExceptionOfType(ToscaPolicyConversionException.class)
216                 .isThrownBy(() -> translator.convertPolicy(testPol));
217
218         testPol.setProperties(null);
219         assertThatExceptionOfType(ToscaPolicyConversionException.class)
220                 .isThrownBy(() -> translator.convertPolicy(testPol));
221     }
222
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;
229
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()) {
237                     //
238                     // These fields are required
239                     //
240                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
241                             match.getAttributeDesignator().getAttributeId())) {
242                         assertThat(match.getAttributeValue().getContent()).isNotNull();
243                         foundActor = true;
244                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
245                             match.getAttributeDesignator().getAttributeId())) {
246                         assertThat(match.getAttributeValue().getContent()).isNotNull();
247                         foundOperation = true;
248                     } else {
249                         //
250                         // These fields are optional
251                         //
252                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
253                                 match.getAttributeDesignator().getAttributeId())) {
254                             assertThat(policy.getProperties()).containsKey("target");
255                             foundTarget = true;
256                         }
257                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
258                                 match.getAttributeDesignator().getAttributeId())) {
259                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
260                             foundControlLoop = true;
261                         }
262                         /*
263                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
264                                 match.getAttributeDesignator().getAttributeId())) {
265                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
266                             foundTimeRange = true;
267                         }
268                         */
269                     }
270                 }
271             }
272         }
273         assertThat(foundActor && foundOperation).isTrue();
274         if (policy.getProperties().containsKey("target")) {
275             assertThat(foundTarget).isTrue();
276         }
277         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
278             assertThat(foundControlLoop).isTrue();
279         }
280         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
281             assertThat(xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition())
282                 .hasAtLeastOneElementOfType(VariableDefinitionType.class);
283         }
284     }
285
286     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
287         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
288             if (! (rule instanceof RuleType)) {
289                 continue;
290             }
291             assertThat(((RuleType) rule).getCondition()).isNotNull();
292             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
293         }
294     }
295
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)) {
301                 continue;
302             }
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);
311                             foundTarget = true;
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;
317                         }
318                     }
319                 }
320             }
321         }
322         assertThat(foundTarget && foundMinOrMax).isTrue();
323     }
324
325     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
326         boolean foundBlacklist = false;
327         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
328             if (! (rule instanceof RuleType)) {
329                 continue;
330             }
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");
342                         //
343                         // This just checks that policy did have a blacklist in it.
344                         //
345                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
346                         foundBlacklist = true;
347                     }
348                 }
349             }
350         }
351         assertThat(foundBlacklist).isTrue();
352     }
353
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)) {
358                 continue;
359             }
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);
370                     }
371                 }
372             }
373         }
374     }
375 }