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