From 95c95b08ae8fa2592852168ec11b9aff3a6a31d5 Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Tue, 3 Oct 2023 09:58:40 +0100 Subject: [PATCH] TLS support in sdc-fe Signed-off-by: MichaelMorris Issue-ID: SDC-4642 Change-Id: I960c0a114889c7b5c1c7924cefff93168132e2b6 --- .../sdc-catalog-fe/files/default/org.onap.sdc.p12 | Bin 4443 -> 0 bytes .../files/default/org.onap.sdc.trust.jks | Bin 1413 -> 0 bytes .../sdc-catalog-fe/recipes/FE_6_locate_keystore.rb | 21 --------------- .../recipes/FE_6_setup_key_and_trust_store.rb | 21 +++++++++++++++ .../recipes/FE_7_create_jetty_modules.rb | 7 ++--- .../sdc-catalog-fe/templates/default/ssl-ini.erb | 27 ++++++++++++------- .../sdc-frontend/chef-solo/roles/catalog-fe.json | 2 +- .../sdc/fe/impl/HealthCheckScheduledTask.java | 23 ++++++++++++++-- .../openecomp/sdc/fe/servlets/SSLProxyServlet.java | 13 ++++++++- .../http/client/api/HttpConnectionMngFactory.java | 10 ++++++- .../sdc/common/http/config/ClientCertificate.java | 30 ++++++++------------- 11 files changed, 97 insertions(+), 57 deletions(-) delete mode 100644 catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/files/default/org.onap.sdc.p12 delete mode 100644 catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/files/default/org.onap.sdc.trust.jks delete mode 100644 catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_locate_keystore.rb create mode 100644 catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_setup_key_and_trust_store.rb diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/files/default/org.onap.sdc.p12 b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/files/default/org.onap.sdc.p12 deleted file mode 100644 index 446856071b3803dbafd2f94dfec5f62e06e8155b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4443 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 diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_locate_keystore.rb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_locate_keystore.rb deleted file mode 100644 index 50cb2639e8..0000000000 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_locate_keystore.rb +++ /dev/null @@ -1,21 +0,0 @@ -directory "Jetty_etcdir_creation" do - path "#{ENV['JETTY_BASE']}/etc" - owner "#{ENV['JETTY_USER']}" - group "#{ENV['JETTY_GROUP']}" - mode '0755' - action :create -end - -cookbook_file "#{ENV['JETTY_BASE']}/etc/org.onap.sdc.p12" do - source "org.onap.sdc.p12" - owner "#{ENV['JETTY_USER']}" - group "#{ENV['JETTY_GROUP']}" - mode 0755 -end - -cookbook_file "#{ENV['JETTY_BASE']}/etc/org.onap.sdc.trust.jks" do - source "org.onap.sdc.trust.jks" - owner "#{ENV['JETTY_USER']}" - group "#{ENV['JETTY_GROUP']}" - mode 0755 -end diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_setup_key_and_trust_store.rb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_setup_key_and_trust_store.rb new file mode 100644 index 0000000000..2585d1b449 --- /dev/null +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_6_setup_key_and_trust_store.rb @@ -0,0 +1,21 @@ +#Set the http module option +if node['FE'][:tls_cert] + execute "generate-keystore" do + command "openssl pkcs12 -inkey #{node['FE'][:tls_key]} -in #{node['FE'][:tls_cert]} -export -out /tmp/keystore.pkcs12 -passin pass:#{node['FE'][:tls_password]} -passout pass:#{node['FE'][:tls_password]}" + end + + execute "import-keystore" do + command "keytool -importkeystore -srcstoretype PKCS12 -srckeystore /tmp/keystore.pkcs12 -srcstorepass #{node['FE'][:tls_password]} -destkeystore #{ENV['JETTY_BASE']}/#{node['FE'][:keystore_path]} -deststorepass #{node['FE'][:keystore_password]} -noprompt" + end +end + +if node['FE'][:ca_cert] + execute "delete-existing-ca-alias" do + command "keytool -delete -alias sdc-be -storepass #{node['FE'][:truststore_password]} -keystore #{ENV['JETTY_BASE']}/#{node['FE'][:truststore_path]}" + returns [0, 1] + end + + execute "generate-truststore" do + command "keytool -import -alias sdc-be -file #{node['FE'][:ca_cert]} -storetype JKS -keystore #{ENV['JETTY_BASE']}/#{node['FE'][:truststore_path]} -storepass #{node['FE'][:truststore_password]} -noprompt" + end +end diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_7_create_jetty_modules.rb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_7_create_jetty_modules.rb index 734c05ae02..3a7433e9df 100644 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_7_create_jetty_modules.rb +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_7_create_jetty_modules.rb @@ -49,8 +49,9 @@ template "ssl-ini" do mode "0755" variables({ :https_port => "#{node['FE'][:https_port]}" , - :jetty_keystore_pwd => "#{node['jetty'][:keystore_pwd]}" , - :jetty_keymanager_pwd => "#{node['jetty'][:keymanager_pwd]}" , - :jetty_truststore_pwd => "#{node['jetty'][:truststore_pwd]}" + :keystore_path => "#{node['FE'][:keystore_path]}" , + :keystore_password => "#{node['FE'][:keystore_password]}" , + :truststore_path => "#{node['FE'][:truststore_path]}" , + :truststore_password => "#{node['FE'][:truststore_password]}" }) end diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/ssl-ini.erb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/ssl-ini.erb index 278fdea2ae..d3c8bc187c 100644 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/ssl-ini.erb +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/ssl-ini.erb @@ -42,33 +42,42 @@ jetty.ssl.port=<%= @https_port %> ## See http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html ## Keystore file path (relative to $jetty.base) -jetty.sslContext.keyStorePath=etc/org.onap.sdc.p12 +<% unless @keystore_path.nil? || @keystore_path.strip.empty? -%> +jetty.sslContext.keyStorePath=<%= @keystore_path %> +<% end -%> ## Truststore file path (relative to $jetty.base) -jetty.sslContext.trustStorePath=etc/org.onap.sdc.trust.jks +<% unless @truststore_path.nil? || @truststore_path.strip.empty? -%> +jetty.sslContext.trustStorePath=<%= @truststore_path %> +<% end -%> ## Keystore password -# jetty.sslContext.keyStorePassword=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 -jetty.sslContext.keyStorePassword=<%= @jetty_keystore_pwd %> +<% unless @keystore_password.nil? || @keystore_password.strip.empty? -%> +jetty.sslContext.keyStorePassword=<%= @keystore_password %> +<% end -%> ## Keystore type and provider # jetty.sslContext.keyStoreType=JKS # jetty.sslContext.keyStoreProvider= ## KeyManager password -# jetty.sslContext.keyManagerPassword=OBF:1u2u1wml1z7s1z7a1wnl1u2g -jetty.sslContext.keyManagerPassword=<%= @jetty_keymanager_pwd %> +<% unless @keystore_password.nil? || @keystore_password.strip.empty? -%> +jetty.sslContext.keyManagerPassword=<%= @keystore_password %> +<% end -%> ## Truststore password -# jetty.sslContext.trustStorePassword=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 -jetty.sslContext.trustStorePassword=<%= @jetty_truststore_pwd %> +# tp<%= @truststore_password %>end +# kp<%= @keystore_password %>end +<% unless @truststore_password.nil? || @truststore_password.strip.empty? -%> +jetty.sslContext.trustStorePassword=<%= @truststore_password %> +<% end -%> ## Truststore type and provider # jetty.sslContext.trustStoreType=JKS # jetty.sslContext.trustStoreProvider= ## whether client certificate authentication is required -# jetty.sslContext.needClientAuth=false +jetty.sslContext.needClientAuth=<%= !@truststore_password.nil? && !@truststore_password.strip.empty? %> ## Whether client certificate authentication is desired # jetty.sslContext.wantClientAuth=false diff --git a/catalog-fe/sdc-frontend/chef-solo/roles/catalog-fe.json b/catalog-fe/sdc-frontend/chef-solo/roles/catalog-fe.json index 44bb56b5be..815a38c39a 100644 --- a/catalog-fe/sdc-frontend/chef-solo/roles/catalog-fe.json +++ b/catalog-fe/sdc-frontend/chef-solo/roles/catalog-fe.json @@ -15,7 +15,7 @@ "recipe[sdc-catalog-fe::FE_3_errors_config]", "recipe[sdc-catalog-fe::FE_4_logback]", "recipe[sdc-catalog-fe::FE_5_rest_configuration]", - "recipe[sdc-catalog-fe::FE_6_locate_keystore]", + "recipe[sdc-catalog-fe::FE_6_setup_key_and_trust_store]", "recipe[sdc-catalog-fe::FE_7_create_jetty_modules]", "recipe[sdc-catalog-fe::FE_8_prepareProbeFile]" ], diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/HealthCheckScheduledTask.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/HealthCheckScheduledTask.java index 2d99f84b9a..0db9fe9a44 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/HealthCheckScheduledTask.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/impl/HealthCheckScheduledTask.java @@ -37,15 +37,22 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; + +import javax.servlet.ServletException; + import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.onap.config.api.JettySSLUtils; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.api.HealthCheckInfo; import org.openecomp.sdc.common.api.HealthCheckWrapper; import org.openecomp.sdc.common.config.EcompErrorEnum; import org.openecomp.sdc.common.http.client.api.HttpRequest; import org.openecomp.sdc.common.http.client.api.HttpResponse; +import org.openecomp.sdc.common.http.config.ClientCertificate; import org.openecomp.sdc.common.http.config.HttpClientConfig; import org.openecomp.sdc.common.http.config.Timeouts; import org.openecomp.sdc.common.impl.ExternalConfiguration; @@ -116,7 +123,9 @@ public class HealthCheckScheduledTask implements Runnable { if (healthCheckUrl != null) { ObjectMapper mapper = new ObjectMapper(); try { - HttpResponse response = HttpRequest.get(healthCheckUrl, new HttpClientConfig(new Timeouts(connectTimeoutMs, readTimeoutMs))); + HttpClientConfig clientConfig = new HttpClientConfig(new Timeouts(connectTimeoutMs, readTimeoutMs), getHttpClientCertificate()); + + HttpResponse response = HttpRequest.get(healthCheckUrl, clientConfig); int beStatus = response.getStatusCode(); if (beStatus == HttpStatus.SC_OK || beStatus == HttpStatus.SC_INTERNAL_SERVER_ERROR) { String beJsonResponse = response.getResponse(); @@ -135,6 +144,15 @@ public class HealthCheckScheduledTask implements Runnable { String compName = requestedByBE ? Constants.HC_COMPONENT_FE : baseComponent; return Collections.singletonList(new HealthCheckInfo(compName, HealthCheckInfo.HealthCheckStatus.DOWN, null, description.toString())); } + + private ClientCertificate getHttpClientCertificate() { + ClientCertificate clientCertificate = new ClientCertificate(); + clientCertificate.setKeyStore(JettySSLUtils.getSSLConfig().getKeystorePath()); + clientCertificate.setKeyStorePassword(JettySSLUtils.getSSLConfig().getKeystorePass(), false); + clientCertificate.setTrustStore(JettySSLUtils.getSSLConfig().getTruststorePath()); + clientCertificate.setTrustStorePassword(JettySSLUtils.getSSLConfig().getTruststorePass()); + return clientCertificate; + } private String getExternalComponentHcUri(String baseComponent) { String healthCheckUri = null; @@ -197,7 +215,8 @@ public class HealthCheckScheduledTask implements Runnable { ErrorLogOptionalData errorLogOptionalData = ErrorLogOptionalData.newBuilder().targetEntity(LOG_TARGET_ENTITY_BE) .targetServiceName(LOG_SERVICE_NAME).build(); try { - HttpResponse response = HttpRequest.get(redirectedUrl, new HttpClientConfig(new Timeouts(connectTimeoutMs, readTimeoutMs))); + HttpClientConfig clientConfig = new HttpClientConfig(new Timeouts(connectTimeoutMs, readTimeoutMs), getHttpClientCertificate()); + HttpResponse response = HttpRequest.get(redirectedUrl, clientConfig); log.debug("HC call to BE - status code is {}", response.getStatusCode()); String beJsonResponse = response.getResponse(); feAggHealthCheck = getFeHealthCheckInfos(gson, beJsonResponse); diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java index 891bc4ae34..0923716bd0 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java @@ -20,9 +20,11 @@ package org.openecomp.sdc.fe.servlets; import javax.servlet.ServletException; + import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.proxy.ProxyServlet; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.onap.config.api.JettySSLUtils; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.fe.config.Configuration; import org.openecomp.sdc.fe.config.ConfigurationManager; @@ -52,8 +54,17 @@ public abstract class SSLProxyServlet extends ProxyServlet { } private HttpClient getSecureHttpClient() throws ServletException { + final JettySSLUtils.JettySslConfig sslConfig = JettySSLUtils.getSSLConfig(); + SslContextFactory sslContextFactory = new SslContextFactory.Client(); + sslContextFactory.setKeyStorePath(sslConfig.getKeystorePath()); + sslContextFactory.setKeyStorePassword(sslConfig.getKeystorePass()); + sslContextFactory.setKeyManagerPassword(sslConfig.getKeystorePass()); + sslContextFactory.setTrustStorePath(sslConfig.getTruststorePath()); + sslContextFactory.setTrustStorePassword(sslConfig.getTruststorePass()); + sslContextFactory.setKeyStorePath(sslConfig.getKeystorePath()); + // Instantiate HttpClient with the SslContextFactory - final var httpClient = new HttpClient(new SslContextFactory.Client(true)); + final var httpClient = new HttpClient(sslContextFactory); // Configure HttpClient, for example: httpClient.setFollowRedirects(false); // Start HttpClient diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/http/client/api/HttpConnectionMngFactory.java b/common-app-api/src/main/java/org/openecomp/sdc/common/http/client/api/HttpConnectionMngFactory.java index 966bf857c8..8f3e460ca3 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/http/client/api/HttpConnectionMngFactory.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/http/client/api/HttpConnectionMngFactory.java @@ -19,6 +19,7 @@ */ package org.openecomp.sdc.common.http.client.api; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -70,9 +71,10 @@ public class HttpConnectionMngFactory { SSLContextBuilder sslContextBuilder = new SSLContextBuilder(); SSLConnectionSocketFactory sslsf = null; try { - sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy()); if (clientCertificate != null) { setClientSsl(clientCertificate, sslContextBuilder); + } else { + sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy()); } sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), NoopHostnameVerifier.INSTANCE); } catch (GeneralSecurityException e) { @@ -93,6 +95,11 @@ public class HttpConnectionMngFactory { char[] keyStorePassword = clientCertificate.getKeyStorePassword().toCharArray(); KeyStore clientKeyStore = createClientKeyStore(clientCertificate.getKeyStore(), keyStorePassword); sslContextBuilder.loadKeyMaterial(clientKeyStore, keyStorePassword); + if (StringUtils.isEmpty(clientCertificate.getTrustStore())) { + sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy()); + } else { + sslContextBuilder.loadTrustMaterial(new File(clientCertificate.getTrustStore()), clientCertificate.getTrustStorePassword().toCharArray()); + } logger.debug("#setClientSsl - Set Client Certificate authentication"); } catch (IOException | GeneralSecurityException e) { logger.debug("#setClientSsl - Set Client Certificate authentication failed with exception, diasable client SSL authentication ", e); @@ -107,6 +114,7 @@ public class HttpConnectionMngFactory { } return keyStore; } + private String getKeyStoreType(String keyStore) { if (!StringUtils.isEmpty(keyStore)) { diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/http/config/ClientCertificate.java b/common-app-api/src/main/java/org/openecomp/sdc/common/http/config/ClientCertificate.java index 93fc3b9f0f..2946217ebd 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/http/config/ClientCertificate.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/http/config/ClientCertificate.java @@ -21,24 +21,33 @@ package org.openecomp.sdc.common.http.config; import fj.data.Either; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + import org.apache.commons.lang3.StringUtils; import org.onap.sdc.security.SecurityUtil; @EqualsAndHashCode +@Getter +@Setter public class ClientCertificate { private String keyStore; private String keyStorePassword; - + private String trustStore; + private String trustStorePassword; + public ClientCertificate() { } public ClientCertificate(ClientCertificate clientCertificate) { setKeyStore(clientCertificate.getKeyStore()); setKeyStorePassword(clientCertificate.getKeyStorePassword(), false); + setTrustStore(clientCertificate.getTrustStore()); + setTrustStorePassword(clientCertificate.getTrustStorePassword()); } - private void setKeyStorePassword(String keyStorePassword, boolean isEncoded) { + public void setKeyStorePassword(String keyStorePassword, boolean isEncoded) { validate(keyStorePassword); if (isEncoded) { Either passkey = SecurityUtil.decrypt(keyStorePassword); @@ -52,32 +61,15 @@ public class ClientCertificate { } } - public String getKeyStore() { - return keyStore; - } - public void setKeyStore(String keyStore) { validate(keyStore); this.keyStore = keyStore; } - public String getKeyStorePassword() { - return keyStorePassword; - } - public void setKeyStorePassword(String keyStorePassword) { setKeyStorePassword(keyStorePassword, true); } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("ClientCertificate [keyStore="); - builder.append(keyStore); - builder.append("]"); - return builder.toString(); - } - private void validate(String str) { if (StringUtils.isEmpty(str)) { throw new IllegalArgumentException("ClientCertificate keystore and/or kestorePassword cannot be empty"); -- 2.16.6