e4c958b9dff2828d4c2a3b9d236de3a8ec6d0711
[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 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.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;
40 import java.util.Map;
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;
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", "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");
138         //
139         // Get the policies
140         //
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();
146
147                 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
148                     translator.convertPolicy(policy)
149                 ).withMessageContaining(expectedMsg);
150             }
151         }
152     }
153
154     @Test
155     public void testPolicyConversion() throws Exception {
156         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
157         //
158         // Serialize it into a class
159         //
160         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
161         //
162         // Make sure all the fields are setup properly
163         //
164         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
165         jtst.fromAuthorative(serviceTemplate);
166         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
167         //
168         // Get the policies
169         //
170         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
171             for (ToscaPolicy policy : policies.values()) {
172                 //
173                 // Convert the policy
174                 //
175                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
176                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
177                         translator.convertPolicy(policy));
178                     continue;
179                 }
180                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
181                 assertThat(xacmlPolicy).isNotNull();
182                 //
183                 // Let's dump it out
184                 //
185                 ByteArrayOutputStream os = new ByteArrayOutputStream();
186                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
187                 LOGGER.info(os.toString());
188                 //
189                 // Validate the policy
190                 //
191                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
192                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
193                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
194                 validateCommon(policy, xacmlPolicy);
195                 //
196                 // Validate each policy type
197                 //
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);
206                 }
207             }
208         }
209
210         ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
211
212         testPol.setProperties(new LinkedHashMap<>());
213         assertThatExceptionOfType(ToscaPolicyConversionException.class)
214                 .isThrownBy(() -> translator.convertPolicy(testPol));
215
216         testPol.setProperties(null);
217         assertThatExceptionOfType(ToscaPolicyConversionException.class)
218                 .isThrownBy(() -> translator.convertPolicy(testPol));
219     }
220
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;
227
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()) {
235                     //
236                     // These fields are required
237                     //
238                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
239                             match.getAttributeDesignator().getAttributeId())) {
240                         assertThat(match.getAttributeValue().getContent()).isNotNull();
241                         foundActor = true;
242                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
243                             match.getAttributeDesignator().getAttributeId())) {
244                         assertThat(match.getAttributeValue().getContent()).isNotNull();
245                         foundOperation = true;
246                     } else {
247                         //
248                         // These fields are optional
249                         //
250                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
251                                 match.getAttributeDesignator().getAttributeId())) {
252                             assertThat(policy.getProperties()).containsKey("target");
253                             foundTarget = true;
254                         }
255                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
256                                 match.getAttributeDesignator().getAttributeId())) {
257                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
258                             foundControlLoop = true;
259                         }
260                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
261                                 match.getAttributeDesignator().getAttributeId())) {
262                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
263                             foundTimeRange = true;
264                         }
265                     }
266                 }
267             }
268         }
269         assertThat(foundActor && foundOperation).isTrue();
270         if (policy.getProperties().containsKey("target")) {
271             assertThat(foundTarget).isTrue();
272         }
273         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
274             assertThat(foundControlLoop).isTrue();
275         }
276         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
277             assertThat(foundTimeRange).isTrue();
278         }
279     }
280
281     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
282         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
283             if (! (rule instanceof RuleType)) {
284                 continue;
285             }
286             assertThat(((RuleType) rule).getCondition()).isNotNull();
287             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
288         }
289     }
290
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)) {
296                 continue;
297             }
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);
306                             foundTarget = true;
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;
312                         }
313                     }
314                 }
315             }
316         }
317         assertThat(foundTarget && foundMinOrMax).isTrue();
318     }
319
320     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
321         boolean foundBlacklist = false;
322         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
323             if (! (rule instanceof RuleType)) {
324                 continue;
325             }
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");
337                         //
338                         // This just checks that policy did have a blacklist in it.
339                         //
340                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
341                         foundBlacklist = true;
342                     }
343                 }
344             }
345         }
346         assertThat(foundBlacklist).isTrue();
347     }
348
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)) {
353                 continue;
354             }
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);
365                     }
366                 }
367             }
368         }
369     }
370 }