7e5e3ed5b90ffde05af5f441cc88d2059ffba815
[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  * ================================================================================
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.xacml.pdp.application.guard;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
27
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;
37 import java.util.HashMap;
38 import java.util.Map;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
44 import org.junit.Test;
45 import org.onap.policy.common.utils.coder.StandardCoder;
46 import org.onap.policy.common.utils.coder.StandardYamlCoder;
47 import org.onap.policy.common.utils.resources.ResourceUtils;
48 import org.onap.policy.common.utils.resources.TextFileUtils;
49 import org.onap.policy.models.decisions.concepts.DecisionRequest;
50 import org.onap.policy.models.decisions.concepts.DecisionResponse;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
53 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
54 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
55 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 public class GuardTranslatorTest {
60     private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class);
61     private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
62     private static StandardCoder gson = new StandardCoder();
63
64     private GuardTranslator translator = new GuardTranslator();
65
66     @Test
67     public void testRequest() throws Exception {
68         DecisionRequest decisionRequest = gson.decode(
69                 TextFileUtils.getTextFileAsString(
70                         "src/test/resources/requests/guard.vfCount.json"),
71                         DecisionRequest.class);
72         Request xacmlRequest = translator.convertRequest(decisionRequest);
73
74         assertThat(xacmlRequest).isNotNull();
75     }
76
77     @Test
78     public void testResponse() {
79         StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK);
80         StdMutableResult result = new StdMutableResult(Decision.PERMIT, status);
81         StdMutableResponse response = new StdMutableResponse(result);
82
83         DecisionResponse decisionResponse = translator.convertResponse(response);
84         assertThat(decisionResponse).isNotNull();
85         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
86
87         result = new StdMutableResult(Decision.DENY, status);
88         response = new StdMutableResponse(result);
89         decisionResponse = translator.convertResponse(response);
90         assertThat(decisionResponse).isNotNull();
91         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString());
92
93         result = new StdMutableResult(Decision.INDETERMINATE, status);
94         response = new StdMutableResponse(result);
95         decisionResponse = translator.convertResponse(response);
96         assertThat(decisionResponse).isNotNull();
97         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
98     }
99
100
101     @Test
102     public void testBadPolicies() throws Exception {
103         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
104         //
105         // Serialize it into a class
106         //
107         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
108         //
109         // Make sure all the fields are setup properly
110         //
111         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
112         jtst.fromAuthorative(serviceTemplate);
113         final ToscaServiceTemplate completedJtst = jtst.toAuthorative();
114         //
115         // Expected message for given policy name
116         //
117         final Map<String, String> name2message = new HashMap<>();
118         name2message.put("frequency-missing-properties", "Missing property limit");
119         name2message.put("frequency-timewindow", "timeWindow is not an integer");
120         name2message.put("minmax-notarget", "Missing target field in minmax policy");
121         name2message.put("minmax-nominmax", "Missing min or max field in minmax policy");
122         name2message.put("blacklist-noblacklist", "Missing blacklist");
123         name2message.put("filter-noalgorithm", "Missing algorithm");
124         name2message.put("filter-badalgorithm",
125                             "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
126         name2message.put("filter-nofilter", "Missing filters");
127         name2message.put("filter-nocollection", "Filters is not a collection");
128         name2message.put("filter-noarray", "Filters is not a collection");
129         name2message.put("filter-missingfield", "Missing \'field\' from filter");
130         name2message.put("filter-badfield", "Unexpected value for field in filter");
131         name2message.put("filter-missingfilter", "Missing \'filter\' from filter");
132         name2message.put("filter-missingfunction", "Missing \'function\' from filter");
133         name2message.put("filter-badfunction", "Unexpected value for function in filter");
134         name2message.put("filter-missingblacklist", "Missing \'blacklist\' from filter");
135         name2message.put("filter-badblacklist", "Unexpected value for blacklist in filter");
136         //
137         // Get the policies
138         //
139         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
140             for (ToscaPolicy policy : policies.values()) {
141                 LOGGER.info("Testing policy " + policy.getName());
142                 String expectedMsg = name2message.get(policy.getName());
143                 assertThat(expectedMsg).as(policy.getName()).isNotNull();
144
145                 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
146                     translator.convertPolicy(policy)
147                 ).withMessageContaining(expectedMsg);
148             }
149         }
150     }
151
152     @Test
153     public void testPolicyConversion() throws Exception {
154         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
155         //
156         // Serialize it into a class
157         //
158         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
159         //
160         // Make sure all the fields are setup properly
161         //
162         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
163         jtst.fromAuthorative(serviceTemplate);
164         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
165         //
166         // Get the policies
167         //
168         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
169             for (ToscaPolicy policy : policies.values()) {
170                 //
171                 // Convert the policy
172                 //
173                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
174                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
175                         translator.convertPolicy(policy));
176                     continue;
177                 }
178                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
179                 assertThat(xacmlPolicy).isNotNull();
180                 //
181                 // Let's dump it out
182                 //
183                 ByteArrayOutputStream os = new ByteArrayOutputStream();
184                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
185                 LOGGER.info(os.toString());
186                 //
187                 // Validate the policy
188                 //
189                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
190                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
191                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
192                 validateCommon(policy, xacmlPolicy);
193                 //
194                 // Validate each policy type
195                 //
196                 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
197                     validateFrequency(policy, xacmlPolicy);
198                 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
199                     validateMinMax(policy, xacmlPolicy);
200                 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
201                     validateBlacklist(policy, xacmlPolicy);
202                 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
203                     validateFilter(policy, xacmlPolicy);
204                 }
205             }
206         }
207     }
208
209     private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
210         boolean foundActor = false;
211         boolean foundOperation = false;
212         boolean foundTarget = false;
213         boolean foundControlLoop = false;
214         boolean foundTimeRange = false;
215
216         assertThat(xacmlPolicy.getTarget()).isNotNull();
217         assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
218         for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
219             assertThat(anyOf.getAllOf()).isNotEmpty();
220             for (AllOfType allOf : anyOf.getAllOf()) {
221                 assertThat(allOf.getMatch()).isNotEmpty();
222                 for (MatchType match : allOf.getMatch()) {
223                     //
224                     // These fields are required
225                     //
226                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
227                             match.getAttributeDesignator().getAttributeId())) {
228                         assertThat(match.getAttributeValue().getContent()).isNotNull();
229                         foundActor = true;
230                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
231                             match.getAttributeDesignator().getAttributeId())) {
232                         assertThat(match.getAttributeValue().getContent()).isNotNull();
233                         foundOperation = true;
234                     } else {
235                         //
236                         // These fields are optional
237                         //
238                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
239                                 match.getAttributeDesignator().getAttributeId())) {
240                             assertThat(policy.getProperties()).containsKey("target");
241                             foundTarget = true;
242                         }
243                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
244                                 match.getAttributeDesignator().getAttributeId())) {
245                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
246                             foundControlLoop = true;
247                         }
248                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
249                                 match.getAttributeDesignator().getAttributeId())) {
250                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
251                             foundTimeRange = true;
252                         }
253                     }
254                 }
255             }
256         }
257         assertThat(foundActor && foundOperation).isTrue();
258         if (policy.getProperties().containsKey("target")) {
259             assertThat(foundTarget).isTrue();
260         }
261         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
262             assertThat(foundControlLoop).isTrue();
263         }
264         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
265             assertThat(foundTimeRange).isTrue();
266         }
267     }
268
269     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
270         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
271             if (! (rule instanceof RuleType)) {
272                 continue;
273             }
274             assertThat(((RuleType) rule).getCondition()).isNotNull();
275             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
276         }
277     }
278
279     private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
280         boolean foundTarget = false;
281         boolean foundMinOrMax = false;
282         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
283             if (! (rule instanceof RuleType)) {
284                 continue;
285             }
286             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
287                 assertThat(anyOf.getAllOf()).isNotEmpty();
288                 for (AllOfType allOf : anyOf.getAllOf()) {
289                     assertThat(allOf.getMatch()).isNotEmpty();
290                     for (MatchType match : allOf.getMatch()) {
291                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
292                                 match.getAttributeDesignator().getAttributeId())) {
293                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
294                             foundTarget = true;
295                         } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
296                                 match.getAttributeDesignator().getAttributeId())) {
297                             assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
298                                     GuardTranslator.FIELD_MAX);
299                             foundMinOrMax = true;
300                         }
301                     }
302                 }
303             }
304         }
305         assertThat(foundTarget && foundMinOrMax).isTrue();
306     }
307
308     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
309         boolean foundBlacklist = false;
310         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
311             if (! (rule instanceof RuleType)) {
312                 continue;
313             }
314             assertThat(((RuleType) rule).getTarget()).isNotNull();
315             assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
316             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
317                 assertThat(anyOf.getAllOf()).isNotEmpty();
318                 for (AllOfType allOf : anyOf.getAllOf()) {
319                     assertThat(allOf.getMatch()).isNotEmpty();
320                     assertThat(allOf.getMatch()).hasSize(1);
321                     for (MatchType match : allOf.getMatch()) {
322                         assertThat(match.getAttributeDesignator().getAttributeId())
323                                 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
324                         assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
325                         //
326                         // This just checks that policy did have a blacklist in it.
327                         //
328                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
329                         foundBlacklist = true;
330                     }
331                 }
332             }
333         }
334         assertThat(foundBlacklist).isTrue();
335     }
336
337     private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
338         assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
339         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
340             if (! (rule instanceof RuleType)) {
341                 continue;
342             }
343             assertThat(((RuleType) rule).getTarget()).isNotNull();
344             assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
345             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
346                 assertThat(anyOf.getAllOf()).isNotEmpty();
347                 for (AllOfType allOf : anyOf.getAllOf()) {
348                     assertThat(allOf.getMatch()).isNotEmpty();
349                     assertThat(allOf.getMatch()).hasSize(1);
350                     for (MatchType match : allOf.getMatch()) {
351                         assertThat(match.getAttributeDesignator().getAttributeId())
352                             .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);
353                     }
354                 }
355             }
356         }
357     }
358 }