From b6a282ed0f584cff4aa4b571bf826bf546616d2a Mon Sep 17 00:00:00 2001 From: ilanap Date: Thu, 26 Mar 2020 12:50:06 +0200 Subject: Initial fix for https call to plugins Creates an http/https client to check whether plugin is online. missing UI fixes still Issue-ID: SDC-2843 Signed-off-by: ilanap Change-Id: I06ee08c73881c8a8c458198f9b6a0f9df1021f52 Signed-off-by: ilanap (cherry picked from commit 7422f22140b7ce24e3e735dabaa325e2f7a4fc92) --- .../org/openecomp/sdc/fe/impl/PluginStatusBL.java | 60 +++++++++- .../org/openecomp/sdc/fe/utils/JettySSLUtils.java | 128 +++++++++++++++++++++ 2 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 catalog-fe/src/main/java/org/openecomp/sdc/fe/utils/JettySSLUtils.java (limited to 'catalog-fe/src') diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/PluginStatusBL.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/PluginStatusBL.java index 14b76d4679..a2b0adb4fe 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/PluginStatusBL.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/PluginStatusBL.java @@ -26,28 +26,46 @@ import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpHead; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; + import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.InvalidArgumentException; import org.openecomp.sdc.fe.config.ConfigurationManager; import org.openecomp.sdc.fe.config.PluginsConfiguration; import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin; +import org.openecomp.sdc.fe.utils.JettySSLUtils; import java.io.IOException; +import java.security.GeneralSecurityException; public class PluginStatusBL { private static final Logger log = Logger.getLogger(PluginStatusBL.class.getName()); + private static final String MAX_CONNECTION_POOL = "maxOutgoingConnectionPoolTotal"; + private static final String MAX_ROUTE_POOL = "maxOutgoingPerRoute"; private final Gson gson; - private final CloseableHttpClient client; + private CloseableHttpClient client; private final PluginsConfiguration pluginsConfiguration; private RequestConfig requestConfig; public PluginStatusBL() { this.pluginsConfiguration = ConfigurationManager.getConfigurationManager().getPluginsConfiguration(); - this.client = HttpClients.createDefault(); this.gson = new GsonBuilder().setPrettyPrinting().create(); + // check if we have secure connections in the plugin list, if not - we won't bother with it + try { + this.client = getPooledClient(this.hasSecuredPlugins()); + } catch (Exception e){ + log.error("Could not initialize the Https client: {}", e.getMessage()); + log.debug("Exception:",e); + } } public PluginStatusBL(CloseableHttpClient client) { @@ -58,6 +76,39 @@ public class PluginStatusBL { } + private boolean hasSecuredPlugins() { + if (this.getPluginsList() != null) { + return pluginsConfiguration.getPluginsList().stream() + .anyMatch(plugin -> plugin.getPluginDiscoveryUrl().toLowerCase().startsWith("https")); + } + return false; + + } + + private CloseableHttpClient getPooledClient(boolean isSecured) throws GeneralSecurityException, IOException { + final PoolingHttpClientConnectionManager poolingConnManager; + if (!isSecured) { + poolingConnManager + = new PoolingHttpClientConnectionManager(); + } else { + SSLConnectionSocketFactory s = new SSLConnectionSocketFactory( + JettySSLUtils.getSslContext(), + new NoopHostnameVerifier()); + + Registry registry = RegistryBuilder.create() + .register("http", new PlainConnectionSocketFactory()) + .register("https", s) + .build(); + poolingConnManager + = new PoolingHttpClientConnectionManager(registry); + } + int maxTotal = System.getProperties().containsKey(MAX_CONNECTION_POOL) ? Integer.parseInt(System.getProperty(MAX_CONNECTION_POOL)) : 5; + int routeMax = System.getProperties().containsKey(MAX_ROUTE_POOL) ? Integer.parseInt(System.getProperty(MAX_ROUTE_POOL)) : 20; + poolingConnManager.setMaxTotal(maxTotal); + poolingConnManager.setDefaultMaxPerRoute(routeMax); + return HttpClients.custom().setConnectionManager(poolingConnManager).setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); + } + public String getPluginsList() { String result = null; @@ -107,7 +158,10 @@ public class PluginStatusBL { HttpHead head = new HttpHead(plugin.getPluginDiscoveryUrl()); head.setConfig(this.requestConfig); - + if (this.client == null) { + log.debug("The plugin {} will not run because https is not configured on the FE server",plugin.getPluginId()); + return false; + } try (CloseableHttpResponse response = this.client.execute(head)) { result = response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK; log.debug("The plugin {} is {} with result {}", plugin.getPluginId(), (result ? "online" : "offline"), result); diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/utils/JettySSLUtils.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/utils/JettySSLUtils.java new file mode 100644 index 0000000000..fb00725a88 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/utils/JettySSLUtils.java @@ -0,0 +1,128 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.utils; + +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.ssl.SSLContexts; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Properties; + +public class JettySSLUtils { + private JettySSLUtils() { + } + + public static JettySslConfig getSSLConfig() throws IOException { + Properties sslProperties = new Properties(); + + String sslPropsPath = System.getenv("JETTY_BASE") + File.separator + "/start.d/ssl.ini"; + File sslPropsFile = new File(sslPropsPath); + try (FileInputStream fis = new FileInputStream(sslPropsFile)) { + sslProperties.load(fis); + } + + return new JettySslConfig(sslProperties); + } + + + public static SSLContext getSslContext() throws GeneralSecurityException, IOException { + JettySSLUtils.JettySslConfig sslProperties = JettySSLUtils.getSSLConfig(); + + KeyStore trustStore = KeyStore.getInstance(sslProperties.getTruststoreType()); + try (FileInputStream instream = new FileInputStream(new File(sslProperties.getTruststorePath())); + ){ + trustStore.load(instream, (sslProperties.getTruststorePass()).toCharArray()); + } + + KeyStore keystore = KeyStore.getInstance(sslProperties.getKeystoreType()); + try (FileInputStream instream = new FileInputStream(new File(sslProperties.getKeystorePath())); + ){ + keystore.load(instream, sslProperties.getKeystorePass().toCharArray()); + } + + // Trust own CA and all self-signed certs + return SSLContexts.custom() + .loadKeyMaterial(keystore, sslProperties.getKeystorePass().toCharArray()) + .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) + .build(); + } + + + public static class JettySslConfig { + Properties sslProperties; + static final String JETTY_BASE = System.getenv("JETTY_BASE"); + + JettySslConfig(Properties sslProperties) { + this.sslProperties = sslProperties; + } + + public String getJettyBase() { + return JettySslConfig.JETTY_BASE; + } + + public String getKeystorePath() { + return sslProperties.getProperty("jetty.sslContext.keyStorePath"); + } + + public String getKeystorePass() { + return sslProperties.getProperty("jetty.sslContext.keyStorePassword"); + } + + public String getKeystoreType() { + return sslProperties.getProperty("jetty.sslContext.keyStoreType"); + } + + public String getTruststorePath() { + return sslProperties.getProperty("jetty.sslContext.trustStorePath"); + } + + public String getTruststorePass() { + return sslProperties.getProperty("jetty.sslContext.trustStorePassword"); + } + + public String getTruststoreType() { + return sslProperties.getProperty("jetty.sslContext.trustStoreType"); + } + + public String getKeyStoreManager() { + return sslProperties.getProperty("jetty.sslContext.keyManagerPassword"); + } + + public Boolean getNeedClientAuth() { + if (sslProperties.containsKey("jetty.sslContext.needClientAuth")) { + return Boolean.valueOf(sslProperties.getProperty("jetty.sslContext.needClientAuth")); + } else { + return Boolean.FALSE; + } + } + + public String getProperty(String key) { + return sslProperties.getProperty(key); + } + + } + +} -- cgit 1.2.3-korg