From 729c50b19a0fc8e475ff56cf1c7c7324e8715ba8 Mon Sep 17 00:00:00 2001 From: "david.mcweeney" Date: Mon, 22 Mar 2021 16:14:07 +0000 Subject: [PATCH] [DMAAP-BC] Add truststore to https client requests Signed-off-by: david.mcweeney Change-Id: Ifd6f05c0769778cee7759b734dce4a2cee99d0a2 Issue-ID: DMAAP-1580 --- .gitignore | 1 + pom.xml | 3 +- .../onap/dmaap/dbcapi/client/DrProvConnection.java | 102 ++++++++++++--------- .../org/onap/dmaap/dbcapi/server/JettyServer.java | 74 ++++++++------- .../org/onap/dmaap/dbcapi/util/DmaapConfig.java | 47 ++++++++-- version.properties | 2 +- 6 files changed, 140 insertions(+), 89 deletions(-) diff --git a/.gitignore b/.gitignore index ccead04..529b290 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ target/ .checkstyle .project .settings +.idea diff --git a/pom.xml b/pom.xml index c39134a..41e8f10 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,7 @@ + 2.0.4-SNAPSHOT 1.5.19 2.13.3 2.9.5 @@ -49,7 +50,6 @@ UTF-8 9.4.36.v20210114 1.0.0 - 2.0.3-SNAPSHOT 4.12 java @@ -163,6 +163,7 @@ org.eclipse.jetty jetty-server ${jettyVersion} + compile org.eclipse.jetty diff --git a/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java b/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java index f268eae..dffe830 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java +++ b/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java @@ -22,6 +22,17 @@ package org.onap.dmaap.dbcapi.client; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.ProtocolException; +import java.net.SocketException; +import java.net.URL; +import java.util.Arrays; +import javax.net.ssl.HttpsURLConnection; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; import org.onap.dmaap.dbcapi.model.ApiError; @@ -30,14 +41,6 @@ import org.onap.dmaap.dbcapi.model.Feed; import org.onap.dmaap.dbcapi.service.DmaapService; import org.onap.dmaap.dbcapi.util.DmaapConfig; -import javax.net.ssl.HttpsURLConnection; -import java.io.*; -import java.net.ConnectException; -import java.net.ProtocolException; -import java.net.SocketException; -import java.net.URL; -import java.util.Arrays; - public class DrProvConnection extends BaseLoggingClass { @@ -127,12 +130,12 @@ public class DrProvConnection extends BaseLoggingClass { uc = (HttpsURLConnection) u.openConnection(); uc.setInstanceFollowRedirects(false); logger.info( "successful connect to " + pURL ); + uc.setSSLSocketFactory(DmaapConfig.getSSLSocketFactory()); return(true); } catch (Exception e) { errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage() ); return(false); } - } public String bodyToString( InputStream is ) { @@ -158,6 +161,7 @@ public class DrProvConnection extends BaseLoggingClass { logger.info( "post fields=" + Arrays.toString(postData) ); String responsemessage = null; String responseBody = null; + int rc = -1; try { logger.info( "uc=" + uc ); @@ -169,8 +173,7 @@ public class DrProvConnection extends BaseLoggingClass { uc.setUseCaches(false); uc.setDoOutput(true); OutputStream os = null; - int rc = -1; - + try { uc.connect(); os = uc.getOutputStream(); @@ -184,13 +187,14 @@ public class DrProvConnection extends BaseLoggingClass { uc.setDoOutput(false); } catch (Exception e) { } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); - responsemessage = uc.getResponseMessage(); - logger.info( "responsemessage=" + responsemessage ); - - + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); if (responsemessage == null) { // work around for glitch in Java 1.7.0.21 and likely others // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is @@ -272,7 +276,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -340,7 +347,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -421,7 +431,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -530,7 +543,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -608,14 +624,15 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); logger.info( "responsemessage=" + responsemessage ); - - if (responsemessage == null) { @@ -669,29 +686,16 @@ public class DrProvConnection extends BaseLoggingClass { } public String doPutNodes( ApiError err ) { logger.info( "entry: doPutNodes() " ); - //byte[] postData = nodeList.getBytes(); - //logger.info( "get fields=" + postData ); String responsemessage = null; String responseBody = null; try { - uc.setRequestMethod("PUT"); - - //uc.setRequestProperty("Content-Type", subContentType ); - //uc.setRequestProperty( "charset", "utf-8"); - //uc.setRequestProperty( behalfHeader, "DGL" ); - //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); uc.setUseCaches(false); - //uc.setDoOutput(true); - OutputStream os = null; int rc = -1; try { uc.connect(); - //os = uc.getOutputStream(); - //os.write( postData ); - } catch (ProtocolException pe) { // Rcvd error instead of 100-Continue try { @@ -700,7 +704,10 @@ public class DrProvConnection extends BaseLoggingClass { uc.setDoOutput(false); } catch (Exception e) { } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -747,8 +754,6 @@ public class DrProvConnection extends BaseLoggingClass { } public String doDeleteFeed(Feed putFeed, ApiError err) { - //byte[] postData = putFeed.getBytes(); - //logger.info( "post fields=" + postData.toString() ); String responsemessage = null; String responseBody = null; @@ -758,7 +763,6 @@ public class DrProvConnection extends BaseLoggingClass { uc.setRequestProperty("Content-Type", feedContentType ); uc.setRequestProperty( "charset", "utf-8"); uc.setRequestProperty( behalfHeader, putFeed.getOwner() ); - //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); uc.setUseCaches(false); uc.setDoOutput(true); OutputStream os = null; @@ -778,7 +782,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -855,7 +862,7 @@ public class DrProvConnection extends BaseLoggingClass { public String doDeleteDr_Sub(DR_Sub delSub, ApiError err) { logger.info( "entry: doDeleteDr_Sub() " ); byte[] postData = delSub.getBytes(provApi); - logger.info( "post fields=" + postData ); + logger.info( "post fields=" + Arrays.toString(postData)); String responsemessage = null; String responseBody = null; @@ -866,7 +873,6 @@ public class DrProvConnection extends BaseLoggingClass { uc.setRequestProperty("Content-Type", subContentType); uc.setRequestProperty( "charset", "utf-8"); uc.setRequestProperty( behalfHeader, "DGL" ); - //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); uc.setUseCaches(false); uc.setDoOutput(true); OutputStream os = null; @@ -886,7 +892,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); @@ -1022,7 +1031,10 @@ public class DrProvConnection extends BaseLoggingClass { } catch (Exception e) { logger.error(e.getMessage(), e); } - } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); diff --git a/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java b/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java index 74a0fa6..52d7570 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java +++ b/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java @@ -23,17 +23,21 @@ package org.onap.dmaap.dbcapi.server; import com.google.common.collect.Sets; +import java.util.Properties; import javax.servlet.DispatcherType; - import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.*; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; - -import java.util.Properties; +import org.onap.dmaap.dbcapi.util.DmaapConfig; /** * A Jetty server which supports: @@ -43,51 +47,55 @@ import java.util.Properties; */ public class JettyServer extends BaseLoggingClass { - private Server server; + private static final CertificateManager certificateManager = + new CertficateManagerFactory(DmaapConfig.getConfig()).initCertificateManager(); + private final Server server; public Server getServer() { return server; } - public JettyServer(Properties params) throws Exception { + public static CertificateManager getCertificateManager() { + return certificateManager; + } + + public JettyServer(Properties params) { server = new Server(); - int httpPort = Integer.valueOf(params.getProperty("IntHttpPort", "80")); - int sslPort = Integer.valueOf(params.getProperty("IntHttpsPort", "443")); - boolean allowHttp = Boolean.valueOf(params.getProperty("HttpAllowed", "false")); + int httpPort = Integer.parseInt(params.getProperty("IntHttpPort", "80")); + int sslPort = Integer.parseInt(params.getProperty("IntHttpsPort", "443")); + boolean allowHttp = Boolean.parseBoolean(params.getProperty("HttpAllowed", "false")); serverLogger.info("port params: http=" + httpPort + " https=" + sslPort); serverLogger.info("allowHttp=" + allowHttp); // HTTP Server - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecureScheme("https"); - http_config.setSecurePort(sslPort); - http_config.setOutputBufferSize(32768); + HttpConfiguration httpConfig = new HttpConfiguration(); + httpConfig.setSecureScheme("https"); + httpConfig.setSecurePort(sslPort); + httpConfig.setOutputBufferSize(32768); - try (ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config))) { + try (ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfig))) { httpConnector.setPort(httpPort); httpConnector.setIdleTimeout(30000); // HTTPS Server - - HttpConfiguration https_config = new HttpConfiguration(http_config); - https_config.addCustomizer(new SecureRequestCustomizer()); + HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); + httpsConfig.addCustomizer(new SecureRequestCustomizer()); SslContextFactory sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setWantClientAuth(true); - CertificateManager certificateManager = new CertficateManagerFactory(params).initCertificateManager(); if ( ! certificateManager.isReady()) { serverLogger.error("CertificateManager is not ready. NOT starting https!"); } else { - setUpKeystore(certificateManager, sslContextFactory); - setUpTrustStore(certificateManager, sslContextFactory); + setUpKeystore(sslContextFactory); + setUpTrustStore(sslContextFactory); if (sslPort != 0) { try (ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), - new HttpConnectionFactory(https_config))) { + new HttpConnectionFactory(httpsConfig))) { sslConnector.setPort(sslPort); server.addConnector(sslConnector); serverLogger.info("Starting sslConnector on port " + sslPort + " for https"); @@ -125,9 +133,9 @@ public class JettyServer extends BaseLoggingClass { try { serverLogger.info("Starting jetty server"); - String unit_test = params.getProperty("UnitTest", "No"); - serverLogger.info("UnitTest=" + unit_test); - if (unit_test.equals("No")) { + String unitTest = params.getProperty("UnitTest", "No"); + serverLogger.info("UnitTest=" + unitTest); + if (unitTest.equals("No")) { server.start(); server.dumpStdErr(); server.join(); @@ -147,20 +155,20 @@ public class JettyServer extends BaseLoggingClass { Sets.newEnumSet(Sets.newHashSet(DispatcherType.FORWARD, DispatcherType.REQUEST), DispatcherType.class)); } - private void setUpKeystore(CertificateManager certificateManager, SslContextFactory sslContextFactory) { - String keystore = certificateManager.getKeyStoreFile(); + private void setUpKeystore(SslContextFactory sslContextFactory) { + String keystore = JettyServer.certificateManager.getKeyStoreFile(); logger.info("https Server using keystore at " + keystore); sslContextFactory.setKeyStorePath(keystore); - sslContextFactory.setKeyStoreType(certificateManager.getKeyStoreType()); - sslContextFactory.setKeyStorePassword(certificateManager.getKeyStorePassword()); - sslContextFactory.setKeyManagerPassword(certificateManager.getKeyStorePassword()); + sslContextFactory.setKeyStoreType(JettyServer.certificateManager.getKeyStoreType()); + sslContextFactory.setKeyStorePassword(JettyServer.certificateManager.getKeyStorePassword()); + sslContextFactory.setKeyManagerPassword(JettyServer.certificateManager.getKeyStorePassword()); } - private void setUpTrustStore(CertificateManager certificateManager, SslContextFactory sslContextFactory) { - String truststore = certificateManager.getTrustStoreFile(); + private void setUpTrustStore(SslContextFactory sslContextFactory) { + String truststore = JettyServer.certificateManager.getTrustStoreFile(); logger.info("https Server using truststore at " + truststore); sslContextFactory.setTrustStorePath(truststore); - sslContextFactory.setTrustStoreType(certificateManager.getTrustStoreType()); - sslContextFactory.setTrustStorePassword(certificateManager.getTrustStorePassword()); + sslContextFactory.setTrustStoreType(JettyServer.certificateManager.getTrustStoreType()); + sslContextFactory.setTrustStorePassword(JettyServer.certificateManager.getTrustStorePassword()); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java index a47c0bd..51f3e9c 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java +++ b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java @@ -20,30 +20,59 @@ package org.onap.dmaap.dbcapi.util; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; import java.io.*; +import java.security.KeyStore; import java.util.*; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import org.onap.dmaap.dbcapi.server.CertificateManager; +import org.onap.dmaap.dbcapi.server.JettyServer; public class DmaapConfig extends Properties { - /** - * - */ + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(DmaapConfig.class); private static final long serialVersionUID = 1L; - private static String configfname = System.getProperty("ConfigFile", "etc/dmaapbc.properties"); - private static Properties config = new DmaapConfig(); + private static final String CONFIG_FILE_NAME = System.getProperty("ConfigFile", "etc/dmaapbc.properties"); + private static final Properties config = new DmaapConfig(); + public static Properties getConfig() { return(config); } public static String getConfigFileName() { - return(configfname); + return(CONFIG_FILE_NAME); } private DmaapConfig() { - try (InputStream is = new FileInputStream(configfname)){ + try (InputStream is = new FileInputStream(CONFIG_FILE_NAME)){ load(is); } catch (Exception e) { - System.err.println("Unable to load configuration file " + configfname); - org.apache.log4j.Logger.getLogger(getClass()).fatal("Unable to load configuration file " + configfname, e); + logger.error("Unable to load configuration file " + CONFIG_FILE_NAME); System.exit(1); } } + + public static SSLSocketFactory getSSLSocketFactory() { + SSLSocketFactory factory = null; + try { + CertificateManager cm = JettyServer.getCertificateManager(); + String truststore = cm.getTrustStoreFile(); + KeyStore ts = KeyStore.getInstance(cm.getTrustStoreType()); + try (InputStream in = new FileInputStream(truststore)) { + ts.load(in, cm.getTrustStorePassword().toCharArray()); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ts); + TrustManager[] tm = tmf.getTrustManagers(); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, tm, null); + factory = sslContext.getSocketFactory(); + } catch (Exception e) { + logger.error("Exception thrown trying to get SSLSocketFactory: ", e); + } + return factory; + } } diff --git a/version.properties b/version.properties index b535a9b..fb01d58 100644 --- a/version.properties +++ b/version.properties @@ -27,7 +27,7 @@ major=2 minor=0 -patch=3 +patch=4 base_version=${major}.${minor}.${patch} # Release must be completed with git revision # in Jenkins -- 2.16.6