Tie XACML REST Decision
[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.report.HealthCheckReport;
50 import org.onap.policy.common.utils.network.NetworkUtil;
51 import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
52 import org.onap.policy.pdpx.main.parameters.CommonTestData;
53 import org.onap.policy.pdpx.main.parameters.RestServerParameters;
54 import org.onap.policy.pdpx.main.rest.model.StatisticsReport;
55 import org.onap.policy.pdpx.main.startstop.Main;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 /**
60  * Class to perform unit test of {@link XacmlPdpRestServer}.
61  *
62  */
63 public class TestXacmlPdpRestServer {
64
65     private static final Logger LOGGER = LoggerFactory.getLogger(TestXacmlPdpRestServer.class);
66     private static final String NOT_ALIVE = "not alive";
67     private static final String ALIVE = "alive";
68     private static final String SELF = "self";
69     private static final String NAME = "Policy Xacml PDP";
70     private static final String HEALTHCHECK_ENDPOINT = "healthcheck";
71     private static final String STATISTICS_ENDPOINT = "statistics";
72     private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore";
73     private Main main;
74     private XacmlPdpRestServer restServer;
75     private static File applicationPath;
76
77     @ClassRule
78     public static final TemporaryFolder applicationFolder = new TemporaryFolder();
79
80     /**
81      * setup.
82      *
83      * @throws IOException exception if cannot create temporary folder
84      */
85     @BeforeClass
86     public static void setUp() throws IOException {
87         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
88         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
89         applicationPath = applicationFolder.newFolder();
90     }
91
92     /**
93      * Method for cleanup after each test.
94      */
95     @After
96     public void teardown() {
97         try {
98             if (NetworkUtil.isTcpPortOpen("localhost", 6969, 1, 1000L)) {
99                 if (main != null) {
100                     stopXacmlPdpService(main);
101                 }
102
103                 if (restServer != null) {
104                     restServer.stop();
105                 }
106             }
107         } catch (IOException | PolicyXacmlPdpException e) {
108             LOGGER.error("teardown failed", e);
109         } catch (InterruptedException ie) {
110             Thread.interrupted();
111             LOGGER.error("teardown failed", ie);
112         }
113     }
114
115     @Test
116     public void testHealthCheckSuccess() throws IOException, InterruptedException {
117         main = startXacmlPdpService(true);
118         final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT);
119         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
120         validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report);
121     }
122
123     @Test
124     public void testHealthCheckFailure() throws InterruptedException, IOException {
125         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
126         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
127         restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
128         restServer.start();
129         final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT);
130         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
131         validateHealthCheckReport(NAME, SELF, false, 500, NOT_ALIVE, report);
132         assertTrue(restServer.isAlive());
133         assertTrue(restServer.toString().startsWith("XacmlPdpRestServer [servers="));
134     }
135
136     @Test
137     public void testHttpsHealthCheckSuccess() throws Exception {
138         main = startXacmlPdpService(false);
139         final Invocation.Builder invocationBuilder = sendHttpsRequest(HEALTHCHECK_ENDPOINT);
140         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
141         validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report);
142     }
143
144     @Test
145     public void testStatistics_200() throws IOException, InterruptedException {
146         main = startXacmlPdpService(true);
147         Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
148         StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
149         validateStatisticsReport(report, 0, 200);
150         updateXacmlPdpStatistics();
151         invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
152         report = invocationBuilder.get(StatisticsReport.class);
153         validateStatisticsReport(report, 1, 200);
154         XacmlPdpStatisticsManager.resetAllStatistics();
155     }
156
157     @Test
158     public void testStatistics_500() throws IOException, InterruptedException {
159         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
160         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
161         restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
162         restServer.start();
163         final Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
164         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
165         validateStatisticsReport(report, 0, 500);
166         XacmlPdpStatisticsManager.resetAllStatistics();
167     }
168
169     @Test
170     public void testHttpsStatistic() throws Exception {
171         main = startXacmlPdpService(false);
172         final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
173         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
174         validateStatisticsReport(report, 0, 200);
175     }
176
177     @Test
178     public void testStatisticsConstructorIsPrivate() {
179         try {
180             final Constructor<XacmlPdpStatisticsManager> constructor =
181                     XacmlPdpStatisticsManager.class.getDeclaredConstructor();
182             assertTrue(Modifier.isPrivate(constructor.getModifiers()));
183             constructor.setAccessible(true);
184             constructor.newInstance();
185             fail("Expected an InstantiationException to be thrown");
186         } catch (final Exception exp) {
187             assertTrue(exp.getCause().toString().contains("Instantiation of the class is not allowed"));
188         }
189     }
190
191     private Main startXacmlPdpService(final boolean http) {
192         final String[] xacmlPdpConfigParameters = new String[2];
193         if (http) {
194             xacmlPdpConfigParameters[0] = "-c";
195             xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters.json";
196         } else {
197             final Properties systemProps = System.getProperties();
198             systemProps.put("javax.net.ssl.keyStore", KEYSTORE);
199             systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap");
200             System.setProperties(systemProps);
201             xacmlPdpConfigParameters[0] = "-c";
202             xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters_Https.json";
203         }
204         return new Main(xacmlPdpConfigParameters);
205     }
206
207     private void stopXacmlPdpService(final Main main) throws PolicyXacmlPdpException {
208         main.shutdown();
209     }
210
211     private Invocation.Builder sendHttpRequest(final String endpoint) throws IOException, InterruptedException {
212         final ClientConfig clientConfig = new ClientConfig();
213
214         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
215         clientConfig.register(feature);
216
217         final Client client = ClientBuilder.newClient(clientConfig);
218         final WebTarget webTarget = client.target("http://localhost:6969/policy/pdpx/v1/" + endpoint);
219
220         final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
221
222         if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 6, 10000L)) {
223             throw new IllegalStateException("cannot connect to port 6969");
224         }
225         return invocationBuilder;
226     }
227
228     private Invocation.Builder sendHttpsRequest(final String endpoint) throws Exception {
229
230         final TrustManager[] noopTrustManager = new TrustManager[] {new X509TrustManager() {
231
232             @Override
233             public X509Certificate[] getAcceptedIssuers() {
234                 return new X509Certificate[0];
235             }
236
237             @Override
238             public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {}
239
240             @Override
241             public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {}
242         } };
243
244         final SSLContext sc = SSLContext.getInstance("TLSv1.2");
245         sc.init(null, noopTrustManager, new SecureRandom());
246         final ClientBuilder clientBuilder =
247                 ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true);
248         final Client client = clientBuilder.build();
249         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
250         client.register(feature);
251
252         final WebTarget webTarget = client.target("https://localhost:6969/policy/pdpx/v1/" + endpoint);
253
254         final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
255
256         if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 6, 10000L)) {
257             throw new IllegalStateException("cannot connect to port 6969");
258         }
259         return invocationBuilder;
260     }
261
262     private void updateXacmlPdpStatistics() {
263         XacmlPdpStatisticsManager.updateTotalPoliciesCount();
264         XacmlPdpStatisticsManager.updatePermitDecisionsCount();
265         XacmlPdpStatisticsManager.updateDenyDecisionsCount();
266         XacmlPdpStatisticsManager.updateIndeterminantDecisionsCount();
267         XacmlPdpStatisticsManager.updateNotApplicableDecisionsCount();
268     }
269
270     private void validateStatisticsReport(final StatisticsReport report, final int count, final int code) {
271         assertEquals(code, report.getCode());
272         assertEquals(count, report.getTotalPoliciesCount());
273         assertEquals(count, report.getPermitDecisionsCount());
274         assertEquals(count, report.getDenyDecisionsCount());
275         assertEquals(count, report.getIndeterminantDecisionsCount());
276         assertEquals(count, report.getNotApplicableDecisionsCount());
277     }
278
279     private void validateHealthCheckReport(final String name, final String url, final boolean healthy, final int code,
280             final String message, final HealthCheckReport report) {
281         assertEquals(name, report.getName());
282         assertEquals(url, report.getUrl());
283         assertEquals(healthy, report.isHealthy());
284         assertEquals(code, report.getCode());
285         assertEquals(message, report.getMessage());
286     }
287 }