Updates to support fixed guard policy types
[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.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                 if ("frequency-missing-properties".equals(policy.getName())) {
119                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
120                         translator.convertPolicy(policy)
121                     ).withMessageContaining("Missing property limit");
122                 } else if ("frequency-timewindow".equals(policy.getName())) {
123                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
124                         translator.convertPolicy(policy)
125                     ).withMessageContaining("timeWindow is not an integer");
126                 } else if ("minmax-notarget".equals(policy.getName())) {
127                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
128                         translator.convertPolicy(policy)
129                     ).withMessageContaining("Missing target field in minmax policy");
130                 } else if ("minmax-nominmax".equals(policy.getName())) {
131                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
132                         translator.convertPolicy(policy)
133                     ).withMessageContaining("Missing min or max field in minmax policy");
134                 } else if ("blacklist-noblacklist".equals(policy.getName())) {
135                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
136                         translator.convertPolicy(policy)
137                     ).withMessageContaining("Missing blacklist");
138                 }
139             }
140         }
141     }
142
143     @Test
144     public void testPolicyConversion() throws Exception {
145         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
146         //
147         // Serialize it into a class
148         //
149         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
150         //
151         // Make sure all the fields are setup properly
152         //
153         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
154         jtst.fromAuthorative(serviceTemplate);
155         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
156         //
157         // Get the policies
158         //
159         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
160             for (ToscaPolicy policy : policies.values()) {
161                 //
162                 // Convert the policy
163                 //
164                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
165                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
166                         translator.convertPolicy(policy));
167                     continue;
168                 }
169                 PolicyType xacmlPolicy = translator.convertPolicy(policy);
170                 assertThat(xacmlPolicy).isNotNull();
171                 //
172                 // Let's dump it out
173                 //
174                 ByteArrayOutputStream os = new ByteArrayOutputStream();
175                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
176                 LOGGER.info(os.toString());
177                 //
178                 // Validate the policy
179                 //
180                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
181                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
182                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
183                 validateCommon(policy, xacmlPolicy);
184                 //
185                 // Validate each policy type
186                 //
187                 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
188                     validateFrequency(policy, xacmlPolicy);
189                 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
190                     validateMinMax(policy, xacmlPolicy);
191                 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
192                     validateBlacklist(policy, xacmlPolicy);
193                 }
194             }
195         }
196     }
197
198     private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
199         boolean foundActor = false;
200         boolean foundOperation = false;
201         boolean foundTarget = false;
202         boolean foundControlLoop = false;
203         boolean foundTimeRange = false;
204
205         assertThat(xacmlPolicy.getTarget()).isNotNull();
206         assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
207         for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
208             assertThat(anyOf.getAllOf()).isNotEmpty();
209             for (AllOfType allOf : anyOf.getAllOf()) {
210                 assertThat(allOf.getMatch()).isNotEmpty();
211                 for (MatchType match : allOf.getMatch()) {
212                     //
213                     // These fields are required
214                     //
215                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
216                             match.getAttributeDesignator().getAttributeId())) {
217                         assertThat(match.getAttributeValue().getContent()).isNotNull();
218                         foundActor = true;
219                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
220                             match.getAttributeDesignator().getAttributeId())) {
221                         assertThat(match.getAttributeValue().getContent()).isNotNull();
222                         foundOperation = true;
223                     } else {
224                         //
225                         // These fields are optional
226                         //
227                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
228                                 match.getAttributeDesignator().getAttributeId())) {
229                             assertThat(policy.getProperties()).containsKey("target");
230                             foundTarget = true;
231                         }
232                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
233                                 match.getAttributeDesignator().getAttributeId())) {
234                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
235                             foundControlLoop = true;
236                         }
237                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
238                                 match.getAttributeDesignator().getAttributeId())) {
239                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
240                             foundTimeRange = true;
241                         }
242                     }
243                 }
244             }
245         }
246         assertThat(foundActor && foundOperation).isTrue();
247         if (policy.getProperties().containsKey("target")) {
248             assertThat(foundTarget).isTrue();
249         }
250         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
251             assertThat(foundControlLoop).isTrue();
252         }
253         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
254             assertThat(foundTimeRange).isTrue();
255         }
256     }
257
258     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
259         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
260             if (! (rule instanceof RuleType)) {
261                 continue;
262             }
263             assertThat(((RuleType)rule).getCondition()).isNotNull();
264             assertThat(((RuleType)rule).getCondition().getExpression()).isNotNull();
265         }
266     }
267
268     private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
269         boolean foundTarget = false;
270         boolean foundMinOrMax = false;
271         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
272             if (! (rule instanceof RuleType)) {
273                 continue;
274             }
275             for (AnyOfType anyOf : ((RuleType)rule).getTarget().getAnyOf()) {
276                 assertThat(anyOf.getAllOf()).isNotEmpty();
277                 for (AllOfType allOf : anyOf.getAllOf()) {
278                     assertThat(allOf.getMatch()).isNotEmpty();
279                     for (MatchType match : allOf.getMatch()) {
280                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
281                                 match.getAttributeDesignator().getAttributeId())) {
282                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
283                             foundTarget = true;
284                         } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
285                                 match.getAttributeDesignator().getAttributeId())) {
286                             assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
287                                     GuardTranslator.FIELD_MAX);
288                             foundMinOrMax = true;
289                         }
290                     }
291                 }
292             }
293         }
294         assertThat(foundTarget && foundMinOrMax).isTrue();
295     }
296
297     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
298         boolean foundBlacklist = 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_BLACKLIST);
311                             foundBlacklist = true;
312                         }
313                     }
314                 }
315             }
316         }
317         assertThat(foundBlacklist).isTrue();
318     }
319 }