diff options
author | Jim Hahn <jrh3@att.com> | 2019-03-07 11:30:16 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2019-03-08 08:47:36 -0500 |
commit | 2e69b0ad5a696df714cc30c8c47f7a15f9582e6a (patch) | |
tree | c4f022bda0bb54a7c71dd5dc0af6b0857708fa1b | |
parent | 23a3dc4ece2f1533fe1d6b627b5db05e7754a70c (diff) |
Add code to allocate server ports
Added code to find available server ports.
Also added a trust manager that always trusts certificates.
Made trust manager private so we can allocate new ones in the future,
if we decide it isn't safe to re-use the same one over and over.
Modified test code to allocate a port rather than assuming 8180 was
not in use. Also modified retry parameters in other tests.
Added another allocPort() that takes an IP address and then modified
the other two to use that so the code does not have to be duplicated,
while providing more functionality.
Change-Id: I08cf18d923af46b1310d8496498bb1d4a0690b6e
Issue-ID: POLICY-1542
Signed-off-by: Jim Hahn <jrh3@att.com>
3 files changed, 165 insertions, 39 deletions
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java index ca0611cb..d4ccc494 100644 --- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java +++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java @@ -8,9 +8,9 @@ * 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. @@ -25,13 +25,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.util.Map; import java.util.Map.Entry; 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.Entity; @@ -42,6 +38,7 @@ import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; import org.onap.policy.common.endpoints.http.client.HttpClient; import org.onap.policy.common.gson.annotation.GsonJsonIgnore; +import org.onap.policy.common.utils.network.NetworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,7 +51,7 @@ public class JerseyClient implements HttpClient { * Logger. */ private static Logger logger = LoggerFactory.getLogger(JerseyClient.class); - + protected static final String JERSEY_DEFAULT_SERIALIZATION_PROVIDER = "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider"; @@ -74,11 +71,11 @@ public class JerseyClient implements HttpClient { /** * Constructor. - * + * * <p>name the name https is it https or not selfSignedCerts are there self signed certs * hostname the hostname port port being used basePath base context userName user * password password - * + * * @param busTopicParams Input parameters object * @throws KeyManagementException key exception * @throws NoSuchAlgorithmException no algorithm exception @@ -116,25 +113,7 @@ public class JerseyClient implements HttpClient { ClientBuilder clientBuilder; SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); if (this.selfSignedCerts) { - sslContext.init(null, new TrustManager[] {new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // always trusted - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // always trusted - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - } }, new SecureRandom()); + sslContext.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom()); clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier((host, session) -> true); } else { @@ -153,7 +132,7 @@ public class JerseyClient implements HttpClient { } registerSerProviders(busTopicParams.getSerializationProvider()); - + this.client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); this.baseUrl = tmpBaseUrl.append(this.hostname).append(":").append(this.port).append("/") @@ -162,7 +141,7 @@ public class JerseyClient implements HttpClient { /** * Registers the serialization provider(s) with the client. - * + * * @param serializationProvider comma-separated list of serialization providers * @throws ClassNotFoundException if the serialization provider cannot be found */ diff --git a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java index ae70ba44..aca34bbe 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java +++ b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. 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. @@ -23,9 +23,13 @@ package org.onap.policy.common.utils.network; import java.io.IOException; import java.net.ConnectException; import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; - +import java.security.cert.X509Certificate; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,11 +45,80 @@ public class NetworkUtil { */ public static final String IPv4_WILDCARD_ADDRESS = "0.0.0.0"; + + /** + * A trust manager that always trusts certificates. + */ + // @formatter:off + private static final TrustManager[] ALWAYS_TRUST_MANAGER = new TrustManager[] { + new X509TrustManager() { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, + final String authType) {} + + @Override + public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, + final String authType) {} + } + }; + // @formatter:on + private NetworkUtil() { // Empty constructor } /** + * Allocates an available port on which a server may listen. + * + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort() throws IOException { + return allocPort((InetSocketAddress) null); + } + + /** + * Allocates an available port on which a server may listen. + * + * @param hostName the server's host name + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort(String hostName) throws IOException { + return allocPort(new InetSocketAddress(hostName, 0)); + } + + /** + * Allocates an available port on which a server may listen. + * + * @param hostAddr the server's host address on which to listen + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort(InetSocketAddress hostAddr) throws IOException { + try (ServerSocket socket = new ServerSocket()) { + socket.bind(hostAddr); + + return socket.getLocalPort(); + } + } + + /** + * Gets a trust manager that accepts all certificates. + * + * @return a trust manager that accepts all certificates + */ + public static TrustManager[] getAlwaysTrustingManager() { + return ALWAYS_TRUST_MANAGER; + } + + /** * try to connect to $host:$port $retries times while we are getting connection failures. * * @param host host diff --git a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java index 6dd09d6e..c29da2c7 100644 --- a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java +++ b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java @@ -1,15 +1,15 @@ -/*- +/* * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. 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. @@ -20,21 +20,95 @@ package org.onap.policy.common.utils.network; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.io.IOException; - +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class NetworkUtilTest { + protected static Logger logger = LoggerFactory.getLogger(NetworkUtilTest.class); + + private static final String LOCALHOST = "localhost"; @Test public void test() throws InterruptedException, IOException { assertNotNull(NetworkUtil.IPv4_WILDCARD_ADDRESS); - assertFalse(NetworkUtil.isTcpPortOpen("localhost", 8180, 1, 5)); + assertFalse(NetworkUtil.isTcpPortOpen(LOCALHOST, NetworkUtil.allocPort(), 1, 5)); assertNotNull(NetworkUtil.getHostname()); assertNotNull(NetworkUtil.getHostIp()); } + @Test + public void testAlwaysTrustManager() throws Exception { + TrustManager[] mgrarr = NetworkUtil.getAlwaysTrustingManager(); + assertEquals(1, mgrarr.length); + assertTrue(mgrarr[0] instanceof X509TrustManager); + + X509TrustManager mgr = (X509TrustManager) mgrarr[0]; + assertNotNull(mgr.getAcceptedIssuers()); + assertEquals(0, mgr.getAcceptedIssuers().length); + + // these should not throw exceptions + mgr.checkClientTrusted(null, null); + mgr.checkServerTrusted(null, null); + } + + @Test + public void testAllocPort_testAllocPortString__testAllocPortInetSocketAddress() throws Exception { + // allocate wild-card port + int wildCardPort = NetworkUtil.allocPort(); + assertTrue(wildCardPort != 0); + + // verify that we can listen on the port + try (ServerSocket wildSocket = new ServerSocket(wildCardPort)) { + new Accepter(wildSocket).start(); + assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, wildCardPort, 5, 1000L)); + } + + + // allocate port using host name + int localPort = NetworkUtil.allocPort(LOCALHOST); + assertTrue(localPort != 0); + + // the OS should have allocated a new port, even though the first has been closed + assertTrue(localPort != wildCardPort); + + try (ServerSocket localSocket = new ServerSocket()) { + localSocket.bind(new InetSocketAddress(LOCALHOST, localPort)); + new Accepter(localSocket).start(); + assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, localPort, 5, 1000L)); + } + } + + /** + * Thread that accepts a connection on a socket. + */ + private static class Accepter extends Thread { + private ServerSocket socket; + + public Accepter(ServerSocket socket) { + this.socket = socket; + setDaemon(true); + } + + @Override + public void run() { + try (Socket server = socket.accept()) { + // do nothing + + } catch (IOException e) { + logger.error("socket not accepted", e); + } + } + } } |