7bdd4c473002ed1d28c72910d53242ff7168007d
[policy/xacml-pdp.git] / main / src / test / java / org / onap / policy / pdpx / main / CommonRest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019,2023 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * SPDX-License-Identifier: Apache-2.0
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.policy.pdpx.main;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.security.SecureRandom;
32 import java.util.concurrent.atomic.AtomicBoolean;
33 import javax.net.ssl.SSLContext;
34 import javax.ws.rs.client.Client;
35 import javax.ws.rs.client.ClientBuilder;
36 import javax.ws.rs.client.Invocation;
37 import javax.ws.rs.client.WebTarget;
38 import javax.ws.rs.core.MediaType;
39 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
40 import org.junit.After;
41 import org.junit.AfterClass;
42 import org.junit.Before;
43 import org.junit.BeforeClass;
44 import org.onap.policy.common.utils.network.NetworkUtil;
45 import org.onap.policy.common.utils.resources.ResourceUtils;
46 import org.onap.policy.common.utils.security.SelfSignedKeyStore;
47 import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager;
48 import org.onap.policy.pdpx.main.startstop.Main;
49 import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator;
50 import org.springframework.test.util.ReflectionTestUtils;
51
52 /**
53  * Common base class for REST service tests.
54  */
55 public class CommonRest {
56
57     /**
58      * Full path to the config file.
59      */
60     public static final String CONFIG_FILE;
61
62     /**
63      * Path corresponding to {@link #CONFIG_FILE}.
64      */
65     private static final Path CONFIG_PATH;
66
67     /**
68      * Contents read from the "standard" config file, which still contains ${xxx}
69      * place-holders.
70      */
71     private static final String STD_CONFIG;
72
73     /**
74      * Port that was last allocated for the server.
75      */
76     protected static int port;
77
78     /**
79      * "Main" that was last started.
80      */
81     private static Main main;
82
83     /**
84      * Records the "alive" state of the activator while it's temporarily updated by
85      * various junit tests. The {@link #tearDown()} method restores the "alive" state back
86      * to this value.
87      */
88     private boolean activatorWasAlive;
89
90     static {
91         try {
92             File file = new File(ResourceUtils.getFilePath4Resource("parameters/XacmlPdpConfigParameters_Std.json"));
93             STD_CONFIG = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
94
95             file = new File(file.getParentFile(), "Test_XacmlPdpConfigParameters.json");
96             file.deleteOnExit();
97
98             CONFIG_FILE = file.getAbsolutePath();
99             CONFIG_PATH = new File(CONFIG_FILE).toPath();
100
101         } catch (IOException e) {
102             throw new ExceptionInInitializerError(e);
103         }
104     }
105
106     /**
107      * Configures system properties and creates a JSON config file.
108      *
109      * @throws Exception if an error occurs
110      */
111     @BeforeClass
112     public static void setUpBeforeClass() throws Exception {
113         System.setProperty("javax.net.ssl.keyStore", new SelfSignedKeyStore().getKeystoreName());
114         System.setProperty("javax.net.ssl.keyStorePassword", SelfSignedKeyStore.KEYSTORE_PASSWORD);
115
116         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
117         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
118
119         writeJsonConfig();
120
121         final String[] xacmlPdpConfigParameters = {"-c", CommonRest.CONFIG_FILE};
122         main = new Main(xacmlPdpConfigParameters);
123
124         // start xacml rest controller
125         XacmlPdpActivator.getCurrent().enableApi();
126
127         if (!NetworkUtil.isTcpPortOpen("localhost", port, 20, 1000L)) {
128             throw new IllegalStateException("server is not listening on port " + port);
129         }
130     }
131
132     /**
133      * Stops the "Main".
134      */
135     @AfterClass
136     public static void tearDownAfterClass() {
137         stopMain();
138     }
139
140     /**
141      * Resets the statistics.
142      */
143     @Before
144     public void setUp() {
145         activatorWasAlive = XacmlPdpActivator.getCurrent().isAlive();
146         XacmlPdpStatisticsManager.getCurrent().resetAllStatistics();
147     }
148
149     /**
150      * Restores the "alive" status of the activator.
151      */
152     @After
153     public void tearDown() {
154         markActivator(activatorWasAlive);
155     }
156
157     /**
158      * Stops the "main".
159      */
160     protected static void stopMain() {
161         main.shutdown();
162     }
163
164     /**
165      * Writes a JSON config file, substituting an allocated port number for occurrences of
166      * "${port}".
167      *
168      * @return the allocated server port
169      * @throws IOException if the config file cannot be created
170      */
171     public static int writeJsonConfig() throws IOException {
172         port = NetworkUtil.allocPort();
173
174         String config = STD_CONFIG.replace("${port}", String.valueOf(port));
175         Files.write(CONFIG_PATH, config.getBytes(StandardCharsets.UTF_8));
176
177         return port;
178     }
179
180     /**
181      * Sends an HTTPS request to an endpoint of the PDP's REST API.
182      *
183      * @param endpoint target endpoint
184      * @return a request builder
185      * @throws Exception if an error occurs
186      */
187     protected Invocation.Builder sendHttpsRequest(final String endpoint) throws Exception {
188         // always trust the certificate
189         final SSLContext sc = SSLContext.getInstance("TLSv1.2");
190         sc.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom());
191
192         // always trust the host name
193         final ClientBuilder clientBuilder =
194                         ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true);
195
196         final Client client = clientBuilder.build();
197         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
198         client.register(feature);
199
200         final WebTarget webTarget = client.target("https://localhost:" + port + "/policy/pdpx/v1/" + endpoint);
201
202         return webTarget.request(MediaType.APPLICATION_JSON);
203     }
204
205     /**
206      * Mark the activator as dead, but leave its REST server running.
207      */
208     protected void markActivatorDead() {
209         markActivator(false);
210     }
211
212     /**
213      * Changes the internal "alive" status of the activator to a new value.
214      *
215      * @param newAlive the new "alive" status
216      */
217     private void markActivator(boolean newAlive) {
218         Object manager = ReflectionTestUtils.getField(XacmlPdpActivator.getCurrent(), "serviceManager");
219         AtomicBoolean running = (AtomicBoolean) ReflectionTestUtils.getField(manager, "running");
220         running.set(newAlive);
221     }
222 }