From: MichaelMorris Date: Tue, 19 Sep 2023 08:48:04 +0000 (+0100) Subject: sdc-BE TLS support X-Git-Tag: 1.13.6~9 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=sdc.git;a=commitdiff_plain;h=0ce40cecbce00104be54871ce87ca99cef2aa480 sdc-BE TLS support Signed-off-by: MichaelMorris Issue-ID: SDC-4639 Change-Id: Id97c5331b52650f5da25caff4e9ad0166f39202a --- diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_4_jetty_Modules.rb b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_4_jetty_Modules.rb index f029fb07fe..172888c773 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_4_jetty_Modules.rb +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_4_jetty_Modules.rb @@ -41,3 +41,19 @@ template "https-ini" do mode "0755" variables :https_port => "#{node['BE'][:https_port]}" end + +template "ssl-ini" do + path "#{ENV['JETTY_BASE']}/start.d/ssl.ini" + source "ssl-ini.erb" + owner "#{ENV['JETTY_USER']}" + group "#{ENV['JETTY_GROUP']}" + mode "0755" + variables ({ + :https_port => "#{node['BE'][:https_port]}" , + :keystore_path => "#{node['BE'][:keystore_path]}" , + :keystore_password => "#{node['BE'][:keystore_password]}" , + :truststore_path => "#{node['BE'][:truststore_path]}" , + :truststore_password => "#{node['BE'][:truststore_password]}" + }) +end + diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/ssl-ini.erb b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/ssl-ini.erb index 278fdea2ae..d3c8bc187c 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/ssl-ini.erb +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/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-be/src/main/java/org/openecomp/sdc/be/components/kafka/KafkaCommonConfig.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/KafkaCommonConfig.java new file mode 100644 index 0000000000..425b681f4b --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/KafkaCommonConfig.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2023 Nordix Foundation. 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.be.components.kafka; + +import java.util.Properties; +import java.util.UUID; +import org.apache.kafka.clients.CommonClientConfigs; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.config.SaslConfigs; +import org.apache.kafka.common.config.SslConfigs; +import org.onap.config.api.JettySSLUtils; +import org.openecomp.sdc.be.config.DistributionEngineConfiguration; + +public class KafkaCommonConfig { + + private final DistributionEngineConfiguration deConfiguration; + + public KafkaCommonConfig(DistributionEngineConfiguration config){ + this.deConfiguration = config; + } + + public Properties getConsumerProperties(){ + Properties props = new Properties(); + setCommonProperties(props); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + props.put(ConsumerConfig.CLIENT_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerId() + "-consumer-" + UUID.randomUUID()); + props.put(ConsumerConfig.GROUP_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerGroup()); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); + return props; + } + + public Properties getProducerProperties(){ + Properties props = new Properties(); + setCommonProperties(props); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); + props.put(ProducerConfig.CLIENT_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerId() + "-producer-" + UUID.randomUUID()); + + return props; + } + + private void setCommonProperties(Properties props) { + String securityProtocolConfig = System.getenv().getOrDefault("SECURITY_PROTOCOL", "SASL_PLAINTEXT"); + props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, securityProtocolConfig); + props.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, deConfiguration.getKafkaBootStrapServers()); + + if("SSL".equals(securityProtocolConfig)) { + final JettySSLUtils.JettySslConfig sslConfig = JettySSLUtils.getSSLConfig(); + props.put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG, sslConfig.getKeystorePath()); + props.put(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG, sslConfig.getKeystorePass()); + props.put(SslConfigs.SSL_KEY_PASSWORD_CONFIG, sslConfig.getKeyStoreManager()); + props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ""); + props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, sslConfig.getTruststorePath()); + props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, sslConfig.getTruststorePass()); + } else { + props.put(SaslConfigs.SASL_JAAS_CONFIG, getKafkaSaslJaasConfig()); + props.put(SaslConfigs.SASL_MECHANISM, "SCRAM-SHA-512"); + } + } + + /** + * @return The Sasl Jaas Configuration + */ + private String getKafkaSaslJaasConfig() throws KafkaException { + String saslJaasConfFromEnv = System.getenv("SASL_JAAS_CONFIG"); + if(saslJaasConfFromEnv != null) { + return saslJaasConfFromEnv; + } else { + throw new KafkaException("sasl.jaas.config not set for Kafka Consumer"); + } + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaConsumer.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaConsumer.java index 04df4e1fbe..81da06dc74 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaConsumer.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaConsumer.java @@ -25,14 +25,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; -import java.util.UUID; -import org.apache.kafka.clients.CommonClientConfigs; -import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.common.KafkaException; -import org.apache.kafka.common.config.SaslConfigs; import org.openecomp.sdc.be.config.DistributionEngineConfiguration; import org.openecomp.sdc.common.log.wrappers.Logger; @@ -42,30 +38,17 @@ import org.openecomp.sdc.common.log.wrappers.Logger; public class SdcKafkaConsumer { private static final Logger log = Logger.getLogger(SdcKafkaConsumer.class.getName()); - private static final String DEFAULT_SASL_MECHANISM = "SCRAM-SHA-512"; - private final DistributionEngineConfiguration deConfiguration; - private KafkaConsumer kafkaConsumer; + private final KafkaConsumer kafkaConsumer; /** * Constructor setting up the KafkaConsumer from a predefined set of configurations */ public SdcKafkaConsumer(DistributionEngineConfiguration deConfiguration){ log.info("Create SdcKafkaConsumer via constructor"); - Properties properties = new Properties(); + KafkaCommonConfig kafkaCommonConfig = new KafkaCommonConfig(deConfiguration); + Properties properties = kafkaCommonConfig.getConsumerProperties(); this.deConfiguration = deConfiguration; - - properties.put(ConsumerConfig.CLIENT_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerId()+ "-consumer-" + UUID.randomUUID()); - properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); - properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); - properties.put(ConsumerConfig.GROUP_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerGroup()); - properties.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, deConfiguration.getKafkaBootStrapServers()); - properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_PLAINTEXT"); - properties.put(ConsumerConfig.ALLOW_AUTO_CREATE_TOPICS_CONFIG, false); - properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); - properties.put(SaslConfigs.SASL_MECHANISM, getKafkaSaslMechanism()); - - properties.put(SaslConfigs.SASL_JAAS_CONFIG, getKafkaSaslJaasConfig()); kafkaConsumer = new KafkaConsumer<>(properties); } @@ -80,28 +63,6 @@ public class SdcKafkaConsumer { this.kafkaConsumer = kafkaConsumer; } - /** - * - * @return the Sasl Jass Config - */ - private String getKafkaSaslJaasConfig() { - String saslJaasConfFromEnv = System.getenv("SASL_JAAS_CONFIG"); - if(saslJaasConfFromEnv != null) { - return saslJaasConfFromEnv; - } else { - throw new KafkaException("sasl.jaas.config not set for Kafka Consumer"); - } - } - - private static String getKafkaSaslMechanism() throws KafkaException { - String saslMechanism = System.getenv("SASL_MECHANISM"); - if(saslMechanism != null) { - return saslMechanism; - } else { - return DEFAULT_SASL_MECHANISM; - } - } - /** * * @param topic Topic in which to subscribe diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaProducer.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaProducer.java index 7158357799..5db5165b55 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaProducer.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/kafka/SdcKafkaProducer.java @@ -21,13 +21,9 @@ package org.openecomp.sdc.be.components.kafka; import com.google.common.annotations.VisibleForTesting; import java.util.Properties; -import java.util.UUID; -import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.clients.producer.KafkaProducer; -import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.KafkaException; -import org.apache.kafka.common.config.SaslConfigs; import org.openecomp.sdc.be.config.DistributionEngineConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,24 +33,16 @@ import org.slf4j.LoggerFactory; */ public class SdcKafkaProducer { private static final Logger log = LoggerFactory.getLogger(SdcKafkaProducer.class.getName()); - private static final String DEFAULT_SASL_MECHANISM = "SCRAM-SHA-512"; - private KafkaProducer kafkaProducer; + private final KafkaProducer kafkaProducer; /** * Constructor setting up the KafkaProducer from a predefined set of configurations */ public SdcKafkaProducer(DistributionEngineConfiguration deConfiguration) { log.info("Create SdcKafkaProducer via constructor"); - Properties properties = new Properties(); - - properties.put(ProducerConfig.CLIENT_ID_CONFIG, deConfiguration.getDistributionStatusTopic().getConsumerId() + "-producer-" + UUID.randomUUID()); - properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); - properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); - properties.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, deConfiguration.getKafkaBootStrapServers()); - properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_PLAINTEXT"); - properties.put(SaslConfigs.SASL_JAAS_CONFIG, getKafkaSaslJaasConfig()); - properties.put(SaslConfigs.SASL_MECHANISM, getKafkaSaslMechanism()); + KafkaCommonConfig kafkaCommonConfig = new KafkaCommonConfig(deConfiguration); + Properties properties = kafkaCommonConfig.getProducerProperties(); kafkaProducer = new KafkaProducer<>(properties); } @@ -67,31 +55,9 @@ public class SdcKafkaProducer { this.kafkaProducer = kafkaProducer; } - /** - * @return The Sasl Jaas Configuration - */ - private static String getKafkaSaslJaasConfig() throws KafkaException { - String saslJaasConfFromEnv = System.getenv("SASL_JAAS_CONFIG"); - if(saslJaasConfFromEnv != null) { - return saslJaasConfFromEnv; - } else { - throw new KafkaException("sasl.jaas.config not set for Kafka Consumer"); - } - } - - private static String getKafkaSaslMechanism() throws KafkaException { - String saslMechanism = System.getenv("SASL_MECHANISM"); - if(saslMechanism != null) { - return saslMechanism; - } else { - return DEFAULT_SASL_MECHANISM; - } - } - /** * @param message A message to Send * @param topicName The name of the topic to publish to - * @return The status of the send request */ public void send(String message, String topicName) throws KafkaException { ProducerRecord kafkaMessagePayload = new ProducerRecord<>(topicName, "PartitionKey", message); diff --git a/catalog-be/src/main/resources/jetty-ssl.xml b/catalog-be/src/main/resources/jetty-ssl.xml deleted file mode 100644 index 9b375087f1..0000000000 --- a/catalog-be/src/main/resources/jetty-ssl.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - / - - - / - - - - - - - SSL_RSA_WITH_DES_CBC_SHA - SSL_DHE_RSA_WITH_DES_CBC_SHA - SSL_DHE_DSS_WITH_DES_CBC_SHA - SSL_RSA_EXPORT_WITH_RC4_40_MD5 - SSL_RSA_EXPORT_WITH_DES40_CBC_SHA - SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA - SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA - - - - - - - - - - - - - - - - - - - SSLv3 - SSLv2 - - - - - diff --git a/catalog-be/src/main/resources/keystore/README.txt b/catalog-be/src/main/resources/keystore/README.txt deleted file mode 100644 index bbbbd07e27..0000000000 --- a/catalog-be/src/main/resources/keystore/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -keytool -genkeypair -keystore catalogbe.jks -alias catalogbe -keypass Aa123456 -storepass Aa123456 -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=Catalog BE, OU=Development, O=AT&T, L=TLV, C=IL" - - -3650 – 10 years validity -Eyal Sofer – creator -Development – Organization unit -AT&T – Organization -TLV- City -IL – Country code - - -catalogbe.jks – name of keystore -Aa123456 - password - -#In order to generate the password OBF:..., run the following command: -java -cp ../jetty-distribution-9.2.7.v20150116/lib/jetty-http-9.2.7.v20150116.jar:../jetty-distribution-9.2.7.v20150116/lib/jetty-util-9.2.7.v20150116.jar org.eclipse.jetty.util.security.Password Aa123456 \ No newline at end of file diff --git a/catalog-be/src/main/resources/keystore/catalogbe.jks b/catalog-be/src/main/resources/keystore/catalogbe.jks deleted file mode 100644 index 8493a46aca..0000000000 Binary files a/catalog-be/src/main/resources/keystore/catalogbe.jks and /dev/null differ diff --git a/catalog-be/src/main/resources/keystore/catalogbe.jks.pwd b/catalog-be/src/main/resources/keystore/catalogbe.jks.pwd deleted file mode 100644 index b113d7d888..0000000000 --- a/catalog-be/src/main/resources/keystore/catalogbe.jks.pwd +++ /dev/null @@ -1 +0,0 @@ -OBF:1cp61iuj194s194u194w194y1is31cok \ No newline at end of file diff --git a/common/onap-common-configuration-management/onap-configuration-management-api/src/main/java/org/onap/config/api/JettySSLUtils.java b/common/onap-common-configuration-management/onap-configuration-management-api/src/main/java/org/onap/config/api/JettySSLUtils.java index 44280cf105..4d257d1b50 100644 --- a/common/onap-common-configuration-management/onap-configuration-management-api/src/main/java/org/onap/config/api/JettySSLUtils.java +++ b/common/onap-common-configuration-management/onap-configuration-management-api/src/main/java/org/onap/config/api/JettySSLUtils.java @@ -27,19 +27,27 @@ import java.security.KeyStore; import java.util.Properties; import javax.net.ssl.SSLContext; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; public class JettySSLUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(JettySSLUtils.class); private JettySSLUtils() { } - public static JettySslConfig getSSLConfig() throws IOException { + public static JettySslConfig getSSLConfig() { 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); + } catch (IOException exception) { + LOGGER.error("Failed to read '{}'", sslPropsPath, exception); } return new JettySslConfig(sslProperties); } @@ -47,16 +55,22 @@ public class JettySSLUtils { public static SSLContext getSslContext() throws GeneralSecurityException, IOException { 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()); + + final SSLContextBuilder contextBuilder = SSLContexts.custom(); + if (!StringUtils.isEmpty(sslProperties.getTruststorePath())) { + try (FileInputStream instream = new FileInputStream(new File(sslProperties.getTruststorePath()));) { + trustStore.load(instream, (sslProperties.getTruststorePass()).toCharArray()); + contextBuilder.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()); + } } KeyStore keystore = KeyStore.getInstance(sslProperties.getKeystoreType()); - try (FileInputStream instream = new FileInputStream(new File(sslProperties.getKeystorePath()));) { - keystore.load(instream, sslProperties.getKeystorePass().toCharArray()); + if (!StringUtils.isEmpty(sslProperties.getKeystorePath())) { + try (FileInputStream instream = new FileInputStream(new File(sslProperties.getKeystorePath()));) { + keystore.load(instream, sslProperties.getKeystorePass().toCharArray()); + contextBuilder.loadKeyMaterial(keystore, sslProperties.getKeystorePass().toCharArray()); + } } - // Trust own CA and all self-signed certs - return SSLContexts.custom().loadKeyMaterial(keystore, sslProperties.getKeystorePass().toCharArray()) - .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(); + return contextBuilder.build(); } public static class JettySslConfig {