From fc32c230809a051bc1c17e8a2a447210822eebe7 Mon Sep 17 00:00:00 2001 From: liboNet Date: Tue, 18 Dec 2018 09:22:00 +0800 Subject: add Https support for distribution endpoints . add the https into the RestServerParameters interface . update CommonTestData to support https interface . add two cases for healthcheck and statistic https validation . update the package script to use JVM properties . add keystore and truststore to resources dir . update the keystore path for consistency Change-Id: I04b2a3e1afef84eafbb6a22e6fe2122a5a181883 Issue-ID: POLICY-1221 Signed-off-by: liboNet --- .../main/parameters/RestServerParameters.java | 15 ++- .../main/rest/DistributionRestServer.java | 2 + .../main/parameters/CommonTestData.java | 5 +- .../main/rest/TestHttpsDistributionRestServer.java | 143 +++++++++++++++++++++ .../TestHttpsStatisticDistributionRestServer.java | 143 +++++++++++++++++++++ .../DistributionConfigParameters_Https.json | 65 ++++++++++ main/src/test/resources/ssl/policy-keystore | Bin 0 -> 4311 bytes 7 files changed, 370 insertions(+), 3 deletions(-) create mode 100644 main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsDistributionRestServer.java create mode 100644 main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsStatisticDistributionRestServer.java create mode 100644 main/src/test/resources/parameters/DistributionConfigParameters_Https.json create mode 100644 main/src/test/resources/ssl/policy-keystore (limited to 'main/src') diff --git a/main/src/main/java/org/onap/policy/distribution/main/parameters/RestServerParameters.java b/main/src/main/java/org/onap/policy/distribution/main/parameters/RestServerParameters.java index 89a264ab..4685b7d1 100644 --- a/main/src/main/java/org/onap/policy/distribution/main/parameters/RestServerParameters.java +++ b/main/src/main/java/org/onap/policy/distribution/main/parameters/RestServerParameters.java @@ -36,6 +36,7 @@ public class RestServerParameters implements ParameterGroup { private int port; private String userName; private String password; + private boolean https; /** * Constructor for instantiating RestServerParameters. @@ -44,13 +45,16 @@ public class RestServerParameters implements ParameterGroup { * @param port the port * @param userName the user name * @param password the password + * @param https the https */ - public RestServerParameters(final String host, final int port, final String userName, final String password) { + public RestServerParameters(final String host, final int port, final String userName, final String password, + final boolean https) { super(); this.host = host; this.port = port; this.userName = userName; this.password = password; + this.https = https; } /** @@ -99,6 +103,15 @@ public class RestServerParameters implements ParameterGroup { return password; } + /** + * Return the https of this RestServerParameters instance. + * + * @return the password + */ + public boolean isHttps() { + return https; + } + /** * Set the name of this RestServerParameters instance. * diff --git a/main/src/main/java/org/onap/policy/distribution/main/rest/DistributionRestServer.java b/main/src/main/java/org/onap/policy/distribution/main/rest/DistributionRestServer.java index 4e2c8428..748d516d 100644 --- a/main/src/main/java/org/onap/policy/distribution/main/rest/DistributionRestServer.java +++ b/main/src/main/java/org/onap/policy/distribution/main/rest/DistributionRestServer.java @@ -91,6 +91,8 @@ public class DistributionRestServer implements Startable { restServerParameters.getUserName()); props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".password", restServerParameters.getPassword()); + props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".https", + String.valueOf(restServerParameters.isHttps())); return props; } diff --git a/main/src/test/java/org/onap/policy/distribution/main/parameters/CommonTestData.java b/main/src/test/java/org/onap/policy/distribution/main/parameters/CommonTestData.java index 96ec9f93..334aa761 100644 --- a/main/src/test/java/org/onap/policy/distribution/main/parameters/CommonTestData.java +++ b/main/src/test/java/org/onap/policy/distribution/main/parameters/CommonTestData.java @@ -48,6 +48,7 @@ public class CommonTestData { private static final String REST_SERVER_USER = "healthcheck"; private static final int REST_SERVER_PORT = 6969; private static final String REST_SERVER_HOST = "0.0.0.0"; + private static final boolean REST_SERVER_HTTPS = false; public static final String DISTRIBUTION_GROUP_NAME = "SDCDistributionGroup"; public static final String DECODER_TYPE = "DummyDecoder"; public static final String DECODER_CLASS_NAME = "org.onap.policy.distribution.main.testclasses.DummyDecoder"; @@ -82,9 +83,9 @@ public class CommonTestData { final RestServerParameters restServerParameters; if (!isEmpty) { restServerParameters = new RestServerParameters(REST_SERVER_HOST, REST_SERVER_PORT, REST_SERVER_USER, - REST_SERVER_PASSWORD); + REST_SERVER_PASSWORD, REST_SERVER_HTTPS); } else { - restServerParameters = new RestServerParameters(null, 0, null, null); + restServerParameters = new RestServerParameters(null, 0, null, null, false); } return restServerParameters; } diff --git a/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsDistributionRestServer.java b/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsDistributionRestServer.java new file mode 100644 index 00000000..604bdd9a --- /dev/null +++ b/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsDistributionRestServer.java @@ -0,0 +1,143 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2018 Intel. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.distribution.main.rest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Properties; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; + +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.junit.Test; +import org.onap.policy.common.endpoints.report.HealthCheckReport; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.distribution.main.PolicyDistributionException; +import org.onap.policy.distribution.main.parameters.CommonTestData; +import org.onap.policy.distribution.main.parameters.RestServerParameters; +import org.onap.policy.distribution.main.startstop.Main; + +/** + * Class to perform unit test of HealthCheckMonitor. + * + * @author Libo Zhu (libo.zhu@intel.com) + */ +public class TestHttpsDistributionRestServer { + + private static final Logger LOGGER = FlexLogger.getLogger(TestDistributionRestServer.class); + private static final String NOT_ALIVE = "not alive"; + private static final String ALIVE = "alive"; + private static final String SELF = "self"; + private static final String NAME = "Policy SSD"; + private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore"; + + @Test + public void testHealthCheckSuccess() throws PolicyDistributionException, InterruptedException, + KeyManagementException, NoSuchAlgorithmException { + final String reportString = "Report [name=Policy SSD, url=self, healthy=true, code=200, message=alive]"; + final Main main = startDistributionService(); + final HealthCheckReport report = performHealthCheck(); + validateReport(NAME, SELF, true, 200, ALIVE, reportString, report); + stopDistributionService(main); + } + + private Main startDistributionService() { + Properties systemProps = System.getProperties(); + systemProps.put("javax.net.ssl.keyStore", KEYSTORE); + systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap"); + System.setProperties(systemProps); + + final String[] distributionConfigParameters = { "-c", "parameters/DistributionConfigParameters_Https.json" }; + return new Main(distributionConfigParameters); + } + + private void stopDistributionService(final Main main) throws PolicyDistributionException { + main.shutdown(); + } + + private HealthCheckReport performHealthCheck() throws InterruptedException, KeyManagementException, + NoSuchAlgorithmException { + HealthCheckReport response = null; + + TrustManager[] noopTrustManager = new TrustManager[]{ + new X509TrustManager() { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + + SSLContext sc = SSLContext.getInstance("TLSv1.2"); + sc.init(null, noopTrustManager, new SecureRandom()); + final ClientBuilder clientBuilder = + ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true); + final Client client = clientBuilder.build(); + final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34"); + client.register(feature); + + final WebTarget webTarget = client.target("https://localhost:6969/healthcheck"); + + final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); + while (response == null) { + try { + response = invocationBuilder.get(HealthCheckReport.class); + } catch (final Exception exp) { + LOGGER.info("the server is not started yet. We will retry again"); + Thread.sleep(1000); + } + } + return response; + } + + private void validateReport(final String name, final String url, final boolean healthy, final int code, + final String message, final String reportString, final HealthCheckReport report) { + assertEquals(name, report.getName()); + assertEquals(url, report.getUrl()); + assertEquals(healthy, report.isHealthy()); + assertEquals(code, report.getCode()); + assertEquals(message, report.getMessage()); + assertEquals(reportString, report.toString()); + } +} diff --git a/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsStatisticDistributionRestServer.java b/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsStatisticDistributionRestServer.java new file mode 100644 index 00000000..f1beb0af --- /dev/null +++ b/main/src/test/java/org/onap/policy/distribution/main/rest/TestHttpsStatisticDistributionRestServer.java @@ -0,0 +1,143 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2018 Intel. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.distribution.main.rest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Properties; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; + +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.junit.Test; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.distribution.main.PolicyDistributionException; +import org.onap.policy.distribution.main.parameters.CommonTestData; +import org.onap.policy.distribution.main.parameters.RestServerParameters; +import org.onap.policy.distribution.main.startstop.Main; + +/** + * Class to perform unit test of HealthCheckMonitor. + * + * @author Libo Zhu (libo.zhu@intel.com) + */ +public class TestHttpsStatisticDistributionRestServer { + + private static final Logger LOGGER = FlexLogger.getLogger(TestHttpsStatisticDistributionRestServer.class); + private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore"; + + @Test + public void testHealthCheckSuccess() throws PolicyDistributionException, InterruptedException, + KeyManagementException, NoSuchAlgorithmException { + final String reportString = "StatisticsReport [code=200, totalDistributionCount=0, distributionSuccessCount=0, " + + "distributionFailureCount=0, totalDownloadCount=0, " + + "downloadSuccessCount=0, downloadFailureCount=0]"; + final Main main = startDistributionService(); + final StatisticsReport report = performStatisticCheck(); + validateReport(200, 0, 0, 0, 0, 0, 0, reportString, report); + stopDistributionService(main); + } + + private Main startDistributionService() { + Properties systemProps = System.getProperties(); + systemProps.put("javax.net.ssl.keyStore", KEYSTORE); + systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap"); + System.setProperties(systemProps); + + final String[] distributionConfigParameters = { "-c", "parameters/DistributionConfigParameters_Https.json" }; + return new Main(distributionConfigParameters); + } + + private void stopDistributionService(final Main main) throws PolicyDistributionException { + main.shutdown(); + } + + private StatisticsReport performStatisticCheck() throws InterruptedException, KeyManagementException, + NoSuchAlgorithmException { + StatisticsReport response = null; + + TrustManager[] noopTrustManager = new TrustManager[]{ + new X509TrustManager() { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + + SSLContext sc = SSLContext.getInstance("TLSv1.2"); + sc.init(null, noopTrustManager, new SecureRandom()); + final ClientBuilder clientBuilder = + ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true); + final Client client = clientBuilder.build(); + final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34"); + client.register(feature); + + final WebTarget webTarget = client.target("https://localhost:6969/statistics"); + + final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); + while (response == null) { + try { + response = invocationBuilder.get(StatisticsReport.class); + } catch (final Exception exp) { + LOGGER.info("the server is not started yet. We will retry again"); + Thread.sleep(1000); + } + } + return response; + } + + private void validateReport(final int code, final int total, final int successCount, final int failureCount, + final int download, final int downloadSuccess, final int downloadFailure, final String reportString, + final StatisticsReport report) { + assertEquals(code, report.getCode()); + assertEquals(total, report.getTotalDistributionCount()); + assertEquals(successCount, report.getDistributionSuccessCount()); + assertEquals(failureCount, report.getDistributionFailureCount()); + assertEquals(download, report.getTotalDownloadCount()); + assertEquals(downloadSuccess, report.getDownloadSuccessCount()); + assertEquals(downloadFailure, report.getDownloadFailureCount()); + assertEquals(reportString, report.toString()); + } +} diff --git a/main/src/test/resources/parameters/DistributionConfigParameters_Https.json b/main/src/test/resources/parameters/DistributionConfigParameters_Https.json new file mode 100644 index 00000000..6454a42e --- /dev/null +++ b/main/src/test/resources/parameters/DistributionConfigParameters_Https.json @@ -0,0 +1,65 @@ +{ + "name":"SDCDistributionGroup", + "restServerParameters":{ + "host":"0.0.0.0", + "port":6969, + "userName":"healthcheck", + "password":"zb!XztG34", + "https":true + }, + "receptionHandlerParameters":{ + "DummyReceptionHandler":{ + "receptionHandlerType":"DummyReceptionHandler", + "receptionHandlerClassName":"org.onap.policy.distribution.main.testclasses.DummyReceptionHandler", + "receptionHandlerConfigurationName":"dummyReceptionHandlerConfiguration", + "pluginHandlerParameters":{ + "policyDecoders":{ + "DummyDecoder":{ + "decoderType":"DummyDecoder", + "decoderClassName":"org.onap.policy.distribution.main.testclasses.DummyDecoder", + "decoderConfigurationParameters": "dummyDecoderConfiguration" + } + }, + "policyForwarders":{ + "DummyForwarder":{ + "forwarderType":"DummyForwarder", + "forwarderClassName":"org.onap.policy.distribution.main.testclasses.DummyPolicyForwarder", + "forwarderConfigurationParameters": "dummyConfiguration" + } + } + } + } + }, + "receptionHandlerConfigurationParameters":{ + "dummyReceptionHandlerConfiguration":{ + "parameterClassName":"org.onap.policy.distribution.main.testclasses.DummyReceptionHandlerParameterGroup", + "parameters":{ + "myStringParameter": "stringValue", + "myIntegerParameter":20, + "myBooleanParameter": true + } + } + }, + "policyForwarderConfigurationParameters":{ + "dummyConfiguration":{ + "parameterClassName":"org.onap.policy.distribution.main.testclasses.DummyPolicyForwarderParameterGroup", + "parameters":{ + "useHttps": false, + "hostname": "192.168.99.100", + "port": 8081, + "userName": "user", + "password": "pw123", + "isManaged": true + } + } + }, + "policyDecoderConfigurationParameters":{ + "dummyDecoderConfiguration":{ + "parameterClassName":"org.onap.policy.distribution.main.testclasses.DummyPolicyDecoderParameterGroup", + "parameters":{ + "policyName": "SamplePolicy", + "policyType": "DUMMY" + } + } + } +} diff --git a/main/src/test/resources/ssl/policy-keystore b/main/src/test/resources/ssl/policy-keystore new file mode 100644 index 00000000..7d2b1ecc Binary files /dev/null and b/main/src/test/resources/ssl/policy-keystore differ -- cgit 1.2.3-korg