Updates to support fixed guard policy types
[policy/xacml-pdp.git] / applications / guard / src / test / java / org / onap / policy / xacml / pdp / application / guard / CoordinationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019-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
27 import com.att.research.xacml.api.Response;
28 import java.io.File;
29 import java.io.IOException;
30 import java.sql.Date;
31 import java.time.Instant;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Properties;
36 import java.util.ServiceLoader;
37 import java.util.UUID;
38 import javax.persistence.EntityManager;
39 import javax.persistence.Persistence;
40 import org.apache.commons.lang3.tuple.Pair;
41 import org.junit.AfterClass;
42 import org.junit.Before;
43 import org.junit.BeforeClass;
44 import org.junit.ClassRule;
45 import org.junit.FixMethodOrder;
46 import org.junit.Test;
47 import org.junit.rules.TemporaryFolder;
48 import org.junit.runners.MethodSorters;
49 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
50 import org.onap.policy.common.utils.coder.CoderException;
51 import org.onap.policy.common.utils.coder.StandardCoder;
52 import org.onap.policy.common.utils.resources.TextFileUtils;
53 import org.onap.policy.models.decisions.concepts.DecisionRequest;
54 import org.onap.policy.models.decisions.concepts.DecisionResponse;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
56 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
57 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
58 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
59 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
60 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
61 import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao;
62 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
67 public class CoordinationTest {
68
69     private static final Logger LOGGER = LoggerFactory.getLogger(CoordinationTest.class);
70     private static Properties properties = new Properties();
71     private static File propertiesFile;
72     private static RestServerParameters clientParams = new RestServerParameters();
73     private static XacmlApplicationServiceProvider service;
74     private static DecisionRequest requestCl1Node1;
75     @SuppressWarnings("unused")
76     private static DecisionRequest requestCl1Node2;
77     private static DecisionRequest requestCl2Node1;
78     private static DecisionRequest requestCl2Node2;
79     private static StandardCoder gson = new StandardCoder();
80     private static EntityManager em;
81     private static final String DENY = "Deny";
82     private static final String PERMIT = "Permit";
83     private static final String OPEN = "Success";
84     private static final String CLOSE = "Closed";
85
86
87     @ClassRule
88     public static final TemporaryFolder policyFolder = new TemporaryFolder();
89
90     /**
91      * Copies the xacml.properties and policies files into
92      * temporary folder and loads the service provider saving
93      * instance of provider off for other tests to use.
94      */
95     @BeforeClass
96     public static void setup() throws Exception {
97         LOGGER.info("Setting up class");
98         //
99         // Setup our temporary folder
100         //
101         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
102         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
103                 properties, myCreator);
104         //
105         // Load service
106         //
107         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
108                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
109         //
110         // Find the guard service application and save for use in all the tests
111         //
112         StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
113         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
114         while (iterator.hasNext()) {
115             XacmlApplicationServiceProvider application = iterator.next();
116             //
117             // Is it our service?
118             //
119             if (application instanceof GuardPdpApplication) {
120                 //
121                 // Should be the first and only one
122                 //
123                 assertThat(service).isNull();
124                 service = application;
125             }
126             strDump.append(application.applicationName());
127             strDump.append(" supports ");
128             strDump.append(application.supportedPolicyTypes());
129             strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
130         }
131         LOGGER.info("{}", strDump);
132         //
133         // Tell it to initialize based on the properties file
134         // we just built for it.
135         //
136         service.initialize(propertiesFile.toPath().getParent(), clientParams);
137         //
138         // Load Decision Requests
139         //
140         requestCl1Node1 = gson.decode(
141                 TextFileUtils.getTextFileAsString(
142                     "src/test/resources/requests/coordination.cl.1.node.1.json"),
143                     DecisionRequest.class);
144         requestCl2Node1 = gson.decode(
145                 TextFileUtils.getTextFileAsString(
146                     "src/test/resources/requests/coordination.cl.2.node.1.json"),
147                     DecisionRequest.class);
148         requestCl1Node2 = gson.decode(
149                 TextFileUtils.getTextFileAsString(
150                     "src/test/resources/requests/coordination.cl.1.node.2.json"),
151                     DecisionRequest.class);
152         requestCl2Node2 = gson.decode(
153                 TextFileUtils.getTextFileAsString(
154                     "src/test/resources/requests/coordination.cl.2.node.2.json"),
155                     DecisionRequest.class);
156         //
157         // Create EntityManager for manipulating DB
158         //
159         String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
160         em = Persistence.createEntityManagerFactory(
161                 CoordinationTest.properties.getProperty(persistenceUnit), properties)
162                 .createEntityManager();
163     }
164
165     /**
166      * Close the entity manager.
167      */
168     @AfterClass
169     public static void cleanup() throws Exception {
170         if (em != null) {
171             em.close();
172         }
173     }
174
175     /**
176      * Clears the database before each test.
177      *
178      */
179     @Before
180     public void startClean() throws Exception {
181         em.getTransaction().begin();
182         em.createQuery("DELETE FROM Dbao").executeUpdate();
183         em.getTransaction().commit();
184     }
185
186     @Test
187     public void test0Basics() throws ToscaPolicyConversionException {
188         LOGGER.info("**************** Running test0Basics ****************");
189         //
190         // Check the methods in coordination translator that don't get tested by
191         // the application.
192         //
193         CoordinationGuardTranslator translator = new CoordinationGuardTranslator();
194         assertThat(translator.convertRequest(null)).isNull();
195         assertThat(translator.convertResponse(null)).isNull();
196         assertThat(CoordinationGuardTranslator.loadCoordinationDirectiveFromFile(
197                 policyFolder.getRoot().getAbsolutePath() + "/nonexist.yaml")).isNull();
198         CoordinationDirective directive = CoordinationGuardTranslator.loadCoordinationDirectiveFromFile(
199                 "src/test/resources/test-directive.yaml");
200         assertThat(directive).isNotNull();
201     }
202
203     @Test
204     public void test1Coordination() throws CoderException, IOException, XacmlApplicationException {
205         LOGGER.info("**************** Running test1Coordination ****************");
206         //
207         // Now load the test coordination policy - make sure
208         // the pdp can support it and have it load
209         // into the PDP.
210         //
211         List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies(
212                 "src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml", service);
213         assertThat(loadedPolicies).isNotNull();
214         assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.coordination.firstBlocksSecond.test");
215         //
216         // cl1 doesn't have open action: cl2 should get permit
217         //
218         requestAndCheckDecision(requestCl2Node1, PERMIT);
219         //
220         // Open cl2 on node1
221         //
222         insertOperationEvent(requestCl2Node1, OPEN);
223         //
224         // Under current coordination policy cl1 always can go
225         //
226         requestAndCheckDecision(requestCl1Node1, PERMIT);
227         //
228         // Open cl1 on node1
229         //
230         insertOperationEvent(requestCl1Node1, OPEN);
231         //
232         // Close cl2 on node1
233         //
234         insertOperationEvent(requestCl2Node1, CLOSE);
235         //
236         // Try cl2 again, cl1 has open action on node1: should get deny
237         //
238         requestAndCheckDecision(requestCl2Node1, DENY);
239         //
240         // Close cl1 on node1
241         //
242         insertOperationEvent(requestCl1Node1, CLOSE);
243         //
244         // Under current coordination policy cl1 always can go
245         //
246         requestAndCheckDecision(requestCl1Node1, PERMIT);
247         //
248         // Open cl1 on node1
249         //
250         insertOperationEvent(requestCl1Node1, OPEN);
251         //
252         // Try cl2 on node2, cl1 only open on node1: should get permit
253         //
254         requestAndCheckDecision(requestCl2Node2, PERMIT);
255         //
256         // Open cl2 on node2
257         //
258         insertOperationEvent(requestCl2Node2, OPEN);
259         //
260         // Try cl2 on node1, cl1 open on node1: should get DENY
261         //
262         requestAndCheckDecision(requestCl2Node1, DENY);
263     }
264
265     /**
266      * Check that decision matches expectation.
267      *
268      * @param expected from the response
269      * @param response received
270      *
271      **/
272     public void checkDecision(String expected, DecisionResponse response) throws CoderException {
273         LOGGER.info("Looking for {} Decision", expected);
274         assertThat(response).isNotNull();
275         assertThat(response.getStatus()).isNotNull();
276         assertThat(response.getStatus()).isEqualTo(expected);
277         //
278         // Dump it out as Json
279         //
280         LOGGER.info(gson.encode(response));
281     }
282
283     /**
284      * Request a decision and check that it matches expectation.
285      *
286      * @param request to send to Xacml PDP
287      * @param expected from the response
288      *
289      **/
290     public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException {
291         //
292         // Ask for a decision
293         //
294         Pair<DecisionResponse, Response> decision = service.makeDecision(request, null);
295         //
296         // Check decision
297         //
298         checkDecision(expected, decision.getKey());
299     }
300
301     @SuppressWarnings("unchecked")
302     private void insertOperationEvent(DecisionRequest request, String outcome) {
303         //
304         // Get the properties
305         //
306         Map<String, Object> properties = (Map<String, Object>) request.getResource().get("guard");
307         //
308         // Add an entry
309         //
310         Dbao newEntry = new Dbao();
311         newEntry.setActor(properties.get("actor").toString());
312         newEntry.setOperation(properties.get("recipe").toString());
313         newEntry.setClosedLoopName(properties.get("clname").toString());
314         newEntry.setOutcome(outcome);
315         newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
316         newEntry.setEndtime(Date.from(Instant.now()));
317         newEntry.setRequestId(UUID.randomUUID().toString());
318         newEntry.setTarget(properties.get("target").toString());
319         em.getTransaction().begin();
320         em.persist(newEntry);
321         em.getTransaction().commit();
322     }
323 }