07e60c613cf2c22d5e1cb37e0dd2c35451f9c96f
[policy/xacml-pdp.git] /
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.Map;
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;
57
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();
62
63     private GuardTranslator translator = new GuardTranslator();
64
65     @Test
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);
72
73         assertThat(xacmlRequest).isNotNull();
74     }
75
76     @Test
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);
81
82         DecisionResponse decisionResponse = translator.convertResponse(response);
83         assertThat(decisionResponse).isNotNull();
84         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
85
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());
91
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());
97     }
98
99
100     @Test
101     public void testBadPolicies() throws Exception {
102         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
103         //
104         // Serialize it into a class
105         //
106         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
107         //
108         // Make sure all the fields are setup properly
109         //
110         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
111         jtst.fromAuthorative(serviceTemplate);
112         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
113         //
114         // Get the policies
115         //
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 ("blacklist-noalgorithm".equals(policy.getName())) {
140                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
141                         translator.convertPolicy(policy)
142                     ).withMessageContaining("Missing precedence");
143                 } else if ("blacklist-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");
188                 }
189             }
190         }
191     }
192
193     @Test
194     public void testPolicyConversion() throws Exception {
195         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
196         //
197         // Serialize it into a class
198         //
199         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
200         //
201         // Make sure all the fields are setup properly
202         //
203         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
204         jtst.fromAuthorative(serviceTemplate);
205         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
206         //
207         // Get the policies
208         //
209         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
210             for (ToscaPolicy policy : policies.values()) {
211                 //
212                 // Convert the policy
213                 //
214                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
215                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
216                         translator.convertPolicy(policy));
217                     continue;
218                 }
219                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
220                 assertThat(xacmlPolicy).isNotNull();
221                 //
222                 // Let's dump it out
223                 //
224                 ByteArrayOutputStream os = new ByteArrayOutputStream();
225                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
226                 LOGGER.info(os.toString());
227                 //
228                 // Validate the policy
229                 //
230                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
231                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
232                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
233                 validateCommon(policy, xacmlPolicy);
234                 //
235                 // Validate each policy type
236                 //
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);
245                 }
246             }
247         }
248     }
249
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;
256
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()) {
264                     //
265                     // These fields are required
266                     //
267                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
268                             match.getAttributeDesignator().getAttributeId())) {
269                         assertThat(match.getAttributeValue().getContent()).isNotNull();
270                         foundActor = true;
271                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
272                             match.getAttributeDesignator().getAttributeId())) {
273                         assertThat(match.getAttributeValue().getContent()).isNotNull();
274                         foundOperation = true;
275                     } else {
276                         //
277                         // These fields are optional
278                         //
279                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
280                                 match.getAttributeDesignator().getAttributeId())) {
281                             assertThat(policy.getProperties()).containsKey("target");
282                             foundTarget = true;
283                         }
284                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
285                                 match.getAttributeDesignator().getAttributeId())) {
286                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
287                             foundControlLoop = true;
288                         }
289                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
290                                 match.getAttributeDesignator().getAttributeId())) {
291                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
292                             foundTimeRange = true;
293                         }
294                     }
295                 }
296             }
297         }
298         assertThat(foundActor && foundOperation).isTrue();
299         if (policy.getProperties().containsKey("target")) {
300             assertThat(foundTarget).isTrue();
301         }
302         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
303             assertThat(foundControlLoop).isTrue();
304         }
305         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
306             assertThat(foundTimeRange).isTrue();
307         }
308     }
309
310     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
311         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
312             if (! (rule instanceof RuleType)) {
313                 continue;
314             }
315             assertThat(((RuleType) rule).getCondition()).isNotNull();
316             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
317         }
318     }
319
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)) {
325                 continue;
326             }
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);
335                             foundTarget = true;
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;
341                         }
342                     }
343                 }
344             }
345         }
346         assertThat(foundTarget && foundMinOrMax).isTrue();
347     }
348
349     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
350         boolean foundBlacklist = false;
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                                 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
365                         assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
366                         //
367                         // This just checks that policy did have a blacklist in it.
368                         //
369                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
370                         foundBlacklist = true;
371                     }
372                 }
373             }
374         }
375         assertThat(foundBlacklist).isTrue();
376     }
377
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)) {
382                 continue;
383             }
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);
394                     }
395                 }
396             }
397         }
398     }
399 }