Fix trailing space in Info.yaml xacml
[policy/xacml-pdp.git] / main / src / test / java / org / onap / policy / pdpx / main / rest / TestDecision.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved.
4  * Modifications Copyright (C) 2019, 2023-2024 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pdpx.main.rest;
23
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26
27 import com.google.gson.Gson;
28 import com.google.gson.GsonBuilder;
29 import jakarta.ws.rs.client.Entity;
30 import jakarta.ws.rs.core.MediaType;
31 import jakarta.ws.rs.core.Response;
32 import jakarta.ws.rs.core.Response.Status;
33 import java.io.File;
34 import java.io.IOException;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.nio.file.StandardCopyOption;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.Map;
42 import java.util.stream.Stream;
43 import org.junit.jupiter.api.AfterAll;
44 import org.junit.jupiter.api.BeforeAll;
45 import org.junit.jupiter.api.Test;
46 import org.junit.jupiter.api.io.TempDir;
47 import org.onap.policy.common.endpoints.http.client.HttpClient;
48 import org.onap.policy.common.endpoints.http.client.HttpClientConfigException;
49 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
50 import org.onap.policy.common.parameters.rest.RestClientParameters;
51 import org.onap.policy.common.parameters.rest.RestServerParameters;
52 import org.onap.policy.common.parameters.topic.TopicParameterGroup;
53 import org.onap.policy.common.utils.network.NetworkUtil;
54 import org.onap.policy.common.utils.resources.ResourceUtils;
55 import org.onap.policy.models.decisions.concepts.DecisionRequest;
56 import org.onap.policy.models.decisions.concepts.DecisionResponse;
57 import org.onap.policy.models.errors.concepts.ErrorResponse;
58 import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
59 import org.onap.policy.pdpx.main.parameters.CommonTestData;
60 import org.onap.policy.pdpx.main.parameters.XacmlApplicationParameters;
61 import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup;
62 import org.onap.policy.pdpx.main.startstop.Main;
63 import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 class TestDecision {
68
69     private static final Logger LOGGER = LoggerFactory.getLogger(TestDecision.class);
70
71     private static int port;
72     private static Main main;
73     private static HttpClient client;
74     private static final CommonTestData testData = new CommonTestData();
75     private static final String APPLICATION_XACML_XML = "application/xacml+xml";
76     private static final String APPLICATION_XACML_JSON = "application/xacml+json";
77
78     @TempDir
79     static Path appsFolder;
80
81     /**
82      * BeforeClass setup environment.
83      *
84      * @throws IOException Cannot create temp apps folder
85      * @throws Exception   exception if service does not start
86      */
87     @BeforeAll
88     static void beforeClass() throws Exception {
89         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
90         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
91
92         port = NetworkUtil.allocPort();
93
94         //
95         // Copy test directory over of the application directories
96         //
97         Path src = Paths.get("src/test/resources/apps");
98         File apps = appsFolder.resolve("apps").toFile();
99
100         try (Stream<Path> sources = Files.walk(src)) {
101             sources.forEach(source -> copy(source, apps.toPath().resolve(src.relativize(source))));
102         }
103         //
104         // Get the parameters file correct.
105         //
106         RestServerParameters rest =
107             testData.toObject(testData.getRestServerParametersMap(port), RestServerParameters.class);
108         RestClientParameters policyApiParameters =
109             testData.toObject(testData.getPolicyApiParametersMap(false), RestClientParameters.class);
110         TopicParameterGroup topicParameterGroup =
111             testData.toObject(testData.getTopicParametersMap(false), TopicParameterGroup.class);
112         final XacmlApplicationParameters xacmlApplicationParameters =
113             testData.toObject(testData.getXacmlapplicationParametersMap(false,
114                 apps.getAbsolutePath()), XacmlApplicationParameters.class);
115         XacmlPdpParameterGroup params =
116             new XacmlPdpParameterGroup("XacmlPdpParameters", "XacmlPdpGroup", "xacml", rest, policyApiParameters,
117                 topicParameterGroup, xacmlApplicationParameters);
118         final Gson gson = new GsonBuilder().create();
119         File fileParams = appsFolder.resolve("params.json").toFile();
120         String jsonParams = gson.toJson(params);
121         LOGGER.info("Creating new params: {}", jsonParams);
122         Files.write(fileParams.toPath(), jsonParams.getBytes());
123         //
124         // Start the service
125         //
126         main = startXacmlPdpService(fileParams);
127         XacmlPdpActivator.getCurrent().enableApi();
128         //
129         // Make sure it is running
130         //
131         if (!NetworkUtil.isTcpPortOpen("localhost", port, 20, 1000L)) {
132             throw new IllegalStateException("Cannot connect to port " + port);
133         }
134         //
135         // Create a client
136         //
137         client = getNoAuthHttpClient();
138     }
139
140     @AfterAll
141     static void after() {
142         stopXacmlPdpService(main);
143         client.shutdown();
144     }
145
146     @Test
147     void testDecision_UnsupportedAction() {
148         LOGGER.info("Running test testDecision_UnsupportedAction");
149
150         DecisionRequest request = new DecisionRequest();
151         request.setOnapName("DROOLS");
152         request.setAction("foo");
153         Map<String, Object> guard = new HashMap<String, Object>();
154         guard.put("actor", "foo");
155         guard.put("recipe", "bar");
156         guard.put("target", "somevnf");
157         guard.put("clname", "phoneyloop");
158         request.setResource(guard);
159
160         ErrorResponse response = getErrorDecision(request);
161         LOGGER.info("Response {}", response);
162         assertThat(response.getResponseCode()).isEqualTo(Status.BAD_REQUEST);
163         assertThat(response.getErrorMessage()).isEqualToIgnoringCase("No application for action foo");
164     }
165
166     @Test
167     void testDecision_Guard() {
168         LOGGER.info("Running test testDecision_Guard");
169
170         DecisionRequest request = new DecisionRequest();
171         request.setOnapName("DROOLS");
172         request.setAction("guard");
173         Map<String, Object> guard = new HashMap<String, Object>();
174         guard.put("actor", "foo");
175         guard.put("recipe", "bar");
176         guard.put("target", "somevnf");
177         guard.put("clname", "phoneyloop");
178         request.setResource(guard);
179
180         DecisionResponse response = getDecision(request);
181         LOGGER.info("Response {}", response);
182         assertThat(response.getStatus()).isEqualTo("Permit");
183     }
184
185     @Test
186     void testDecision_Native() throws IOException {
187         LOGGER.info("Running test testDecision_Native");
188
189         String xmlRequestAsString = ResourceUtils.getResourceAsString(
190             "src/test/resources/decisions/decision.native.request.xml");
191         if (xmlRequestAsString == null) {
192             throw new IOException("failed to read the xml request");
193         }
194
195         String jsonRequestAsString = ResourceUtils.getResourceAsString(
196             "src/test/resources/decisions/decision.native.request.json");
197         if (jsonRequestAsString == null) {
198             throw new IOException("failed to read the json request");
199         }
200
201         String responseFromXmlRequest = getNativeDecision(xmlRequestAsString, APPLICATION_XACML_XML);
202         LOGGER.info("Response from xml request {}", responseFromXmlRequest);
203         assertThat(responseFromXmlRequest).contains("<Response xmlns=").contains("NotApplicable");
204
205         String responseFromJsonRequest = getNativeDecision(jsonRequestAsString, APPLICATION_XACML_JSON);
206         LOGGER.info("Response from json request {}", responseFromJsonRequest);
207         assertThat(responseFromJsonRequest).contains("\"Response\":").contains("NotApplicable");
208     }
209
210     private static Main startXacmlPdpService(File params) throws PolicyXacmlPdpException {
211         final String[] xacmlPdpConfigParameters = {"-c", params.getAbsolutePath()};
212         return new Main(xacmlPdpConfigParameters);
213     }
214
215     private static void stopXacmlPdpService(final Main main) {
216         main.shutdown();
217     }
218
219     private DecisionResponse getDecision(DecisionRequest request) {
220         Entity<DecisionRequest> entityRequest = Entity.entity(request, MediaType.APPLICATION_JSON);
221         Response response = client.post("/decision", entityRequest, Collections.emptyMap());
222
223         assertEquals(200, response.getStatus());
224
225         return HttpClient.getBody(response, DecisionResponse.class);
226     }
227
228     private String getNativeDecision(String request, String mediaType) {
229         Entity<String> entityRequest = Entity.entity(request, mediaType);
230         Response response = client.post("/xacml", entityRequest, Map.of("Accept", mediaType));
231
232         assertEquals(200, response.getStatus());
233
234         return HttpClient.getBody(response, String.class);
235     }
236
237     private ErrorResponse getErrorDecision(DecisionRequest request) {
238         Entity<DecisionRequest> entityRequest = Entity.entity(request, MediaType.APPLICATION_JSON);
239         Response response = client.post("/decision", entityRequest, Collections.emptyMap());
240
241         assertEquals(400, response.getStatus());
242
243         return HttpClient.getBody(response, ErrorResponse.class);
244     }
245
246     private static HttpClient getNoAuthHttpClient() throws HttpClientConfigException {
247         return HttpClientFactoryInstance.getClientFactory().build(RestClientParameters.builder()
248             .clientName("testDecisionClient")
249             .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(port)
250             .basePath("policy/pdpx/v1")
251             .userName("healthcheck").password("zb!XztG34").managed(true).build());
252     }
253
254     private static void copy(Path source, Path dest) {
255         try {
256             LOGGER.info("Copying {} to {}", source, dest);
257             Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
258         } catch (IOException e) {
259             LOGGER.error("Failed to copy {} to {}", source, dest);
260         }
261     }
262 }