Xacml PDP Register/Unregister Changes
[policy/xacml-pdp.git] / main / src / test / java / org / onap / policy / pdpx / main / rest / TestXacmlPdpRestServer.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdpx.main.rest;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.Modifier;
31 import java.security.SecureRandom;
32 import java.security.cert.X509Certificate;
33 import java.util.Properties;
34 import javax.net.ssl.SSLContext;
35 import javax.net.ssl.TrustManager;
36 import javax.net.ssl.X509TrustManager;
37 import javax.ws.rs.client.Client;
38 import javax.ws.rs.client.ClientBuilder;
39 import javax.ws.rs.client.Invocation;
40 import javax.ws.rs.client.WebTarget;
41 import javax.ws.rs.core.MediaType;
42 import org.glassfish.jersey.client.ClientConfig;
43 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
44 import org.junit.After;
45 import org.junit.BeforeClass;
46 import org.junit.ClassRule;
47 import org.junit.Test;
48 import org.junit.rules.TemporaryFolder;
49 import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException;
50 import org.onap.policy.common.endpoints.report.HealthCheckReport;
51 import org.onap.policy.common.utils.network.NetworkUtil;
52 import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
53 import org.onap.policy.pdpx.main.parameters.CommonTestData;
54 import org.onap.policy.pdpx.main.parameters.RestServerParameters;
55 import org.onap.policy.pdpx.main.rest.model.StatisticsReport;
56 import org.onap.policy.pdpx.main.startstop.Main;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60 /**
61  * Class to perform unit test of {@link XacmlPdpRestServer}.
62  *
63  */
64 public class TestXacmlPdpRestServer {
65
66     private static final Logger LOGGER = LoggerFactory.getLogger(TestXacmlPdpRestServer.class);
67     private static final String NOT_ALIVE = "not alive";
68     private static final String ALIVE = "alive";
69     private static final String SELF = "self";
70     private static final String NAME = "Policy Xacml PDP";
71     private static final String HEALTHCHECK_ENDPOINT = "healthcheck";
72     private static final String STATISTICS_ENDPOINT = "statistics";
73     private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore";
74     private Main main;
75     private XacmlPdpRestServer restServer;
76     private static File applicationPath;
77
78     @ClassRule
79     public static final TemporaryFolder applicationFolder = new TemporaryFolder();
80
81     /**
82      * setup.
83      *
84      * @throws IOException exception if cannot create temporary folder
85      */
86     @BeforeClass
87     public static void setUp() throws IOException {
88         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
89         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
90         applicationPath = applicationFolder.newFolder();
91     }
92
93     /**
94      * Method for cleanup after each test.
95      */
96     @After
97     public void teardown() {
98         try {
99             if (NetworkUtil.isTcpPortOpen("localhost", 6969, 1, 1000L)) {
100                 if (main != null) {
101                     stopXacmlPdpService(main);
102                 }
103
104                 if (restServer != null) {
105                     restServer.stop();
106                 }
107             }
108         } catch (IOException | PolicyXacmlPdpException e) {
109             LOGGER.error("teardown failed", e);
110         } catch (InterruptedException ie) {
111             Thread.interrupted();
112             LOGGER.error("teardown failed", ie);
113         }
114     }
115
116     @Test
117     public void testHealthCheckSuccess() throws IOException, InterruptedException, TopicSinkClientException {
118         main = startXacmlPdpService(true);
119         final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT);
120         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
121         validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report);
122     }
123
124     @Test
125     public void testHealthCheckFailure() throws InterruptedException, IOException {
126         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
127         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
128         restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
129         restServer.start();
130         final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT);
131         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
132         validateHealthCheckReport(NAME, SELF, false, 500, NOT_ALIVE, report);
133         assertTrue(restServer.isAlive());
134         assertTrue(restServer.toString().startsWith("XacmlPdpRestServer [servers="));
135     }
136
137     @Test
138     public void testHttpsHealthCheckSuccess() throws Exception {
139         main = startXacmlPdpService(false);
140         final Invocation.Builder invocationBuilder = sendHttpsRequest(HEALTHCHECK_ENDPOINT);
141         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
142         validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report);
143     }
144
145     @Test
146     public void testStatistics_200() throws IOException, InterruptedException, TopicSinkClientException {
147         main = startXacmlPdpService(true);
148         Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
149         StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
150         validateStatisticsReport(report, 0, 200);
151         updateXacmlPdpStatistics();
152         invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
153         report = invocationBuilder.get(StatisticsReport.class);
154         validateStatisticsReport(report, 1, 200);
155         XacmlPdpStatisticsManager.resetAllStatistics();
156     }
157
158     @Test
159     public void testStatistics_500() throws IOException, InterruptedException {
160         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
161         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
162         restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
163         restServer.start();
164         final Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
165         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
166         validateStatisticsReport(report, 0, 500);
167         XacmlPdpStatisticsManager.resetAllStatistics();
168     }
169
170     @Test
171     public void testHttpsStatistic() throws Exception {
172         main = startXacmlPdpService(false);
173         final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
174         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
175         validateStatisticsReport(report, 0, 200);
176     }
177
178     @Test
179     public void testStatisticsConstructorIsPrivate() {
180         try {
181             final Constructor<XacmlPdpStatisticsManager> constructor =
182                     XacmlPdpStatisticsManager.class.getDeclaredConstructor();
183             assertTrue(Modifier.isPrivate(constructor.getModifiers()));
184             constructor.setAccessible(true);
185             constructor.newInstance();
186             fail("Expected an InstantiationException to be thrown");
187         } catch (final Exception exp) {
188             assertTrue(exp.getCause().toString().contains("Instantiation of the class is not allowed"));
189         }
190     }
191
192     private Main startXacmlPdpService(final boolean http) throws TopicSinkClientException {
193         final String[] xacmlPdpConfigParameters = new String[4];
194         if (http) {
195             xacmlPdpConfigParameters[0] = "-c";
196             xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters.json";
197             xacmlPdpConfigParameters[2] = "-p";
198             xacmlPdpConfigParameters[3] = "parameters/topic.properties";
199         } else {
200             final Properties systemProps = System.getProperties();
201             systemProps.put("javax.net.ssl.keyStore", KEYSTORE);
202             systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap");
203             System.setProperties(systemProps);
204             xacmlPdpConfigParameters[0] = "-c";
205             xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters_Https.json";
206             xacmlPdpConfigParameters[2] = "-p";
207             xacmlPdpConfigParameters[3] = "parameters/topic.properties";
208         }
209         return new Main(xacmlPdpConfigParameters);
210     }
211
212     private void stopXacmlPdpService(final Main main) throws PolicyXacmlPdpException {
213         main.shutdown();
214     }
215
216     private Invocation.Builder sendHttpRequest(final String endpoint) throws IOException, InterruptedException {
217         final ClientConfig clientConfig = new ClientConfig();
218
219         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
220         clientConfig.register(feature);
221
222         final Client client = ClientBuilder.newClient(clientConfig);
223         final WebTarget webTarget = client.target("http://localhost:6969/policy/pdpx/v1/" + endpoint);
224
225         final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
226
227         if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 6, 10000L)) {
228             throw new IllegalStateException("cannot connect to port 6969");
229         }
230         return invocationBuilder;
231     }
232
233     private Invocation.Builder sendHttpsRequest(final String endpoint) throws Exception {
234
235         final TrustManager[] noopTrustManager = new TrustManager[] {new X509TrustManager() {
236
237             @Override
238             public X509Certificate[] getAcceptedIssuers() {
239                 return new X509Certificate[0];
240             }
241
242             @Override
243             public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {}
244
245             @Override
246             public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {}
247         } };
248
249         final SSLContext sc = SSLContext.getInstance("TLSv1.2");
250         sc.init(null, noopTrustManager, new SecureRandom());
251         final ClientBuilder clientBuilder =
252                 ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true);
253         final Client client = clientBuilder.build();
254         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
255         client.register(feature);
256
257         final WebTarget webTarget = client.target("https://localhost:6969/policy/pdpx/v1/" + endpoint);
258
259         final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
260
261         if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 6, 10000L)) {
262             throw new IllegalStateException("cannot connect to port 6969");
263         }
264         return invocationBuilder;
265     }
266
267     private void updateXacmlPdpStatistics() {
268         XacmlPdpStatisticsManager.updateTotalPoliciesCount();
269         XacmlPdpStatisticsManager.updatePermitDecisionsCount();
270         XacmlPdpStatisticsManager.updateDenyDecisionsCount();
271         XacmlPdpStatisticsManager.updateIndeterminantDecisionsCount();
272         XacmlPdpStatisticsManager.updateNotApplicableDecisionsCount();
273     }
274
275     private void validateStatisticsReport(final StatisticsReport report, final int count, final int code) {
276         assertEquals(code, report.getCode());
277         assertEquals(count, report.getTotalPoliciesCount());
278         assertEquals(count, report.getPermitDecisionsCount());
279         assertEquals(count, report.getDenyDecisionsCount());
280         assertEquals(count, report.getIndeterminantDecisionsCount());
281         assertEquals(count, report.getNotApplicableDecisionsCount());
282     }
283
284     private void validateHealthCheckReport(final String name, final String url, final boolean healthy, final int code,
285             final String message, final HealthCheckReport report) {
286         assertEquals(name, report.getName());
287         assertEquals(url, report.getUrl());
288         assertEquals(healthy, report.isHealthy());
289         assertEquals(code, report.getCode());
290         assertEquals(message, report.getMessage());
291     }
292 }