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