Utilize time extensions
[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", "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");
141         //
142         // Get the policies
143         //
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();
149
150                 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
151                     translator.convertPolicy(policy)
152                 ).withMessageContaining(expectedMsg);
153             }
154         }
155     }
156
157     @Test
158     public void testPolicyConversion() throws Exception {
159         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
160         //
161         // Serialize it into a class
162         //
163         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
164         //
165         // Make sure all the fields are setup properly
166         //
167         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
168         jtst.fromAuthorative(serviceTemplate);
169         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
170         //
171         // Get the policies
172         //
173         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
174             for (ToscaPolicy policy : policies.values()) {
175                 //
176                 // Convert the policy
177                 //
178                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
179                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
180                         translator.convertPolicy(policy));
181                     continue;
182                 }
183                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
184                 assertThat(xacmlPolicy).isNotNull();
185                 //
186                 // Let's dump it out
187                 //
188                 ByteArrayOutputStream os = new ByteArrayOutputStream();
189                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
190                 LOGGER.info(os.toString());
191                 //
192                 // Validate the policy
193                 //
194                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
195                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
196                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
197                 validateCommon(policy, xacmlPolicy);
198                 //
199                 // Validate each policy type
200                 //
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);
209                 }
210             }
211         }
212
213         ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
214
215         testPol.setProperties(new LinkedHashMap<>());
216         assertThatExceptionOfType(ToscaPolicyConversionException.class)
217                 .isThrownBy(() -> translator.convertPolicy(testPol));
218
219         testPol.setProperties(null);
220         assertThatExceptionOfType(ToscaPolicyConversionException.class)
221                 .isThrownBy(() -> translator.convertPolicy(testPol));
222     }
223
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;
230
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()) {
238                     //
239                     // These fields are required
240                     //
241                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
242                             match.getAttributeDesignator().getAttributeId())) {
243                         assertThat(match.getAttributeValue().getContent()).isNotNull();
244                         foundActor = true;
245                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
246                             match.getAttributeDesignator().getAttributeId())) {
247                         assertThat(match.getAttributeValue().getContent()).isNotNull();
248                         foundOperation = true;
249                     } else {
250                         //
251                         // These fields are optional
252                         //
253                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
254                                 match.getAttributeDesignator().getAttributeId())) {
255                             assertThat(policy.getProperties()).containsKey("target");
256                             foundTarget = true;
257                         }
258                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
259                                 match.getAttributeDesignator().getAttributeId())) {
260                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
261                             foundControlLoop = true;
262                         }
263                         /*
264                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
265                                 match.getAttributeDesignator().getAttributeId())) {
266                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
267                             foundTimeRange = true;
268                         }
269                         */
270                     }
271                 }
272             }
273         }
274         assertThat(foundActor && foundOperation).isTrue();
275         if (policy.getProperties().containsKey("target")) {
276             assertThat(foundTarget).isTrue();
277         }
278         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
279             assertThat(foundControlLoop).isTrue();
280         }
281         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
282             assertThat(xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition())
283                 .hasAtLeastOneElementOfType(VariableDefinitionType.class);
284         }
285     }
286
287     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
288         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
289             if (! (rule instanceof RuleType)) {
290                 continue;
291             }
292             assertThat(((RuleType) rule).getCondition()).isNotNull();
293             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
294         }
295     }
296
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)) {
302                 continue;
303             }
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);
312                             foundTarget = true;
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;
318                         }
319                     }
320                 }
321             }
322         }
323         assertThat(foundTarget && foundMinOrMax).isTrue();
324     }
325
326     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
327         boolean foundBlacklist = false;
328         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
329             if (! (rule instanceof RuleType)) {
330                 continue;
331             }
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");
343                         //
344                         // This just checks that policy did have a blacklist in it.
345                         //
346                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
347                         foundBlacklist = true;
348                     }
349                 }
350             }
351         }
352         assertThat(foundBlacklist).isTrue();
353     }
354
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)) {
359                 continue;
360             }
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);
371                     }
372                 }
373             }
374         }
375     }
376 }