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