Integrate using Policy Type to find Matchable
[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 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
29 import java.io.File;
30 import java.io.IOException;
31 import java.sql.Date;
32 import java.time.Instant;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Properties;
36 import java.util.ServiceLoader;
37 import java.util.UUID;
38
39 import javax.persistence.EntityManager;
40 import javax.persistence.Persistence;
41
42 import org.apache.commons.lang3.tuple.Pair;
43 import org.junit.AfterClass;
44 import org.junit.Before;
45 import org.junit.BeforeClass;
46 import org.junit.ClassRule;
47 import org.junit.FixMethodOrder;
48 import org.junit.Test;
49 import org.junit.rules.TemporaryFolder;
50 import org.junit.runners.MethodSorters;
51 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
52 import org.onap.policy.common.utils.coder.CoderException;
53 import org.onap.policy.common.utils.coder.StandardCoder;
54 import org.onap.policy.common.utils.resources.TextFileUtils;
55 import org.onap.policy.models.decisions.concepts.DecisionRequest;
56 import org.onap.policy.models.decisions.concepts.DecisionResponse;
57 import org.onap.policy.pdp.xacml.application.common.TestUtils;
58 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
59 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
60 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
61 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
62 import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao;
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:" + System.lineSeparator());
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(System.lineSeparator());
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      * Clears the database before each test.
167      *
168      */
169     @Before
170     public void startClean() throws Exception {
171         em.getTransaction().begin();
172         em.createQuery("DELETE FROM Dbao").executeUpdate();
173         em.getTransaction().commit();
174     }
175
176     /**
177      * Check that decision matches expectation.
178      *
179      * @param expected from the response
180      * @param response received
181      *
182      **/
183     public void checkDecision(String expected, DecisionResponse response) throws CoderException {
184         LOGGER.info("Looking for {} Decision", expected);
185         assertThat(response).isNotNull();
186         assertThat(response.getStatus()).isNotNull();
187         assertThat(response.getStatus()).isEqualTo(expected);
188         //
189         // Dump it out as Json
190         //
191         LOGGER.info(gson.encode(response));
192     }
193
194     /**
195      * Request a decision and check that it matches expectation.
196      *
197      * @param request to send to Xacml PDP
198      * @param expected from the response
199      *
200      **/
201     public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException {
202         //
203         // Ask for a decision
204         //
205         Pair<DecisionResponse, Response> decision = service.makeDecision(request);
206         //
207         // Check decision
208         //
209         checkDecision(expected, decision.getKey());
210     }
211
212     @Test
213     public void test1() throws CoderException, IOException, XacmlApplicationException {
214         LOGGER.info("**************** Running test1 ****************");
215         //
216         // Now load the test coordination policy - make sure
217         // the pdp can support it and have it load
218         // into the PDP.
219         //
220         TestUtils.loadPolicies("src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml",
221                 service);
222         //
223         // cl1 doesn't have open action: cl2 should get permit
224         //
225         requestAndCheckDecision(requestCl2Node1, PERMIT);
226         //
227         // Open cl2 on node1
228         //
229         insertOperationEvent(requestCl2Node1, OPEN);
230         //
231         // Under current coordination policy cl1 always can go
232         //
233         requestAndCheckDecision(requestCl1Node1, PERMIT);
234         //
235         // Open cl1 on node1
236         //
237         insertOperationEvent(requestCl1Node1, OPEN);
238         //
239         // Close cl2 on node1
240         //
241         insertOperationEvent(requestCl2Node1, CLOSE);
242         //
243         // Try cl2 again, cl1 has open action on node1: should get deny
244         //
245         requestAndCheckDecision(requestCl2Node1, DENY);
246         //
247         // Close cl1 on node1
248         //
249         insertOperationEvent(requestCl1Node1, CLOSE);
250         //
251         // Under current coordination policy cl1 always can go
252         //
253         requestAndCheckDecision(requestCl1Node1, PERMIT);
254         //
255         // Open cl1 on node1
256         //
257         insertOperationEvent(requestCl1Node1, OPEN);
258         //
259         // Try cl2 on node2, cl1 only open on node1: should get permit
260         //
261         requestAndCheckDecision(requestCl2Node2, PERMIT);
262         //
263         // Open cl2 on node2
264         //
265         insertOperationEvent(requestCl2Node2, OPEN);
266         //
267         // Try cl2 on node1, cl1 open on node1: should get DENY
268         //
269         requestAndCheckDecision(requestCl2Node1, DENY);
270     }
271
272     @SuppressWarnings("unchecked")
273     private void insertOperationEvent(DecisionRequest request, String outcome) {
274         //
275         // Get the properties
276         //
277         Map<String, Object> properties = (Map<String, Object>) request.getResource().get("guard");
278         //
279         // Add an entry
280         //
281         Dbao newEntry = new Dbao();
282         newEntry.setActor(properties.get("actor").toString());
283         newEntry.setOperation(properties.get("recipe").toString());
284         newEntry.setClosedLoopName(properties.get("clname").toString());
285         newEntry.setOutcome(outcome);
286         newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
287         newEntry.setEndtime(Date.from(Instant.now()));
288         newEntry.setRequestId(UUID.randomUUID().toString());
289         newEntry.setTarget(properties.get("target").toString());
290         em.getTransaction().begin();
291         em.persist(newEntry);
292         em.getTransaction().commit();
293     }
294
295     /**
296      * Close the entity manager.
297      */
298     @AfterClass
299     public static void cleanup() throws Exception {
300         if (em != null) {
301             em.close();
302         }
303     }
304 }