2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.xacml.pdp.application.guard;
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
28 import com.att.research.xacml.api.Response;
30 import java.io.IOException;
32 import java.time.Instant;
33 import java.util.Iterator;
34 import java.util.List;
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;
67 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
68 public class CoordinationTest {
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";
89 public static final TemporaryFolder policyFolder = new TemporaryFolder();
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.
97 public static void setup() throws Exception {
98 LOGGER.info("Setting up class");
100 // Setup our temporary folder
102 XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
103 propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
104 properties, myCreator);
108 ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
109 ServiceLoader.load(XacmlApplicationServiceProvider.class);
111 // Find the guard service application and save for use in all the tests
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();
118 // Is it our service?
120 if (application instanceof GuardPdpApplication) {
122 // Should be the first and only one
124 assertThat(service).isNull();
125 service = application;
127 strDump.append(application.applicationName());
128 strDump.append(" supports ");
129 strDump.append(application.supportedPolicyTypes());
130 strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
132 LOGGER.info("{}", strDump);
134 // Tell it to initialize based on the properties file
135 // we just built for it.
137 service.initialize(propertiesFile.toPath().getParent(), clientParams);
139 // Load Decision Requests
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);
158 // Create EntityManager for manipulating DB
160 String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
161 em = Persistence.createEntityManagerFactory(
162 CoordinationTest.properties.getProperty(persistenceUnit), properties)
163 .createEntityManager();
167 * Close the entity manager.
170 public static void cleanup() throws Exception {
177 * Clears the database before each test.
181 public void startClean() throws Exception {
182 em.getTransaction().begin();
183 em.createQuery("DELETE FROM Dbao").executeUpdate();
184 em.getTransaction().commit();
188 public void test0Basics() throws ToscaPolicyConversionException {
189 LOGGER.info("**************** Running test0Basics ****************");
191 // Check the methods in coordination translator that don't get tested by
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();
206 public void test1Coordination() throws CoderException, IOException, XacmlApplicationException {
207 LOGGER.info("**************** Running test1Coordination ****************");
209 // Now load the test coordination policy - make sure
210 // the pdp can support it and have it load
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");
218 // cl1 doesn't have open action: cl2 should get permit
220 requestAndCheckDecision(requestCl2Node1, PERMIT);
224 insertOperationEvent(requestCl2Node1, OPEN);
226 // Under current coordination policy cl1 always can go
228 requestAndCheckDecision(requestCl1Node1, PERMIT);
232 insertOperationEvent(requestCl1Node1, OPEN);
234 // Close cl2 on node1
236 insertOperationEvent(requestCl2Node1, CLOSE);
238 // Try cl2 again, cl1 has open action on node1: should get deny
240 requestAndCheckDecision(requestCl2Node1, DENY);
242 // Close cl1 on node1
244 insertOperationEvent(requestCl1Node1, CLOSE);
246 // Under current coordination policy cl1 always can go
248 requestAndCheckDecision(requestCl1Node1, PERMIT);
252 insertOperationEvent(requestCl1Node1, OPEN);
256 insertOperationEvent(requestCl2Node2, OPEN);
258 // Try cl2 on node1, cl1 open on node1: should get DENY
260 requestAndCheckDecision(requestCl2Node1, DENY);
264 * Check that decision matches expectation.
266 * @param expected from the response
267 * @param response received
270 public void checkDecision(String expected, DecisionResponse response) throws CoderException {
271 LOGGER.info("Looking for {} Decision", expected);
272 assertThat(response).isNotNull();
273 assertThat(response.getStatus()).isNotNull();
274 assertThat(response.getStatus()).isEqualTo(expected);
276 // Dump it out as Json
278 LOGGER.info(gson.encode(response));
282 * Request a decision and check that it matches expectation.
284 * @param request to send to Xacml PDP
285 * @param expected from the response
288 public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException {
290 // Ask for a decision
292 Pair<DecisionResponse, Response> decision = service.makeDecision(request, null);
296 checkDecision(expected, decision.getKey());
299 @SuppressWarnings("unchecked")
300 private void insertOperationEvent(DecisionRequest request, String outcome) {
302 // Get the properties
304 Map<String, Object> properties = (Map<String, Object>) request.getResource().get("guard");
308 Dbao newEntry = new Dbao();
309 newEntry.setActor(properties.get("actor").toString());
310 newEntry.setOperation(properties.get("recipe").toString());
311 newEntry.setClosedLoopName(properties.get("clname").toString());
312 newEntry.setOutcome(outcome);
313 newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
314 newEntry.setEndtime(Date.from(Instant.now()));
315 newEntry.setRequestId(UUID.randomUUID().toString());
316 newEntry.setTarget(properties.get("target").toString());
317 em.getTransaction().begin();
318 em.persist(newEntry);
319 em.getTransaction().commit();