From e18a8b36358dad4ba1c35649655fe97a1602e96f Mon Sep 17 00:00:00 2001 From: Bernhard Haring Date: Thu, 3 Nov 2022 19:52:19 +0100 Subject: [PATCH] in case of SchemaRegistryBrowserController setup an exception (f.e. ConnectException) the setup method could not load a getWindow witch leads to a NPE which masks the real cause - added flag for suppress cert path validation for schema-registry --- .../SchemaRegistryBrowserController.java | 6 +-- .../at/esque/kafka/cluster/ClusterConfig.java | 14 ++++++ .../cluster/SslSocketFactoryCreator.java | 49 +++++++++++++------ .../kafka/dialogs/ClusterConfigDialog.java | 7 ++- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/src/main/java/at/esque/kafka/SchemaRegistryBrowserController.java b/src/main/java/at/esque/kafka/SchemaRegistryBrowserController.java index ff0c5c2..39f6a15 100644 --- a/src/main/java/at/esque/kafka/SchemaRegistryBrowserController.java +++ b/src/main/java/at/esque/kafka/SchemaRegistryBrowserController.java @@ -47,7 +47,7 @@ public class SchemaRegistryBrowserController { public void setup(ClusterConfig selectedConfig, ConfigHandler configHandler) { schemaRegistryRestService = new RestService(selectedConfig.getSchemaRegistry()); - if (selectedConfig.isSchemaRegistryUseSsl()) { + if (selectedConfig.isSchemaRegistryUseSsl() || selectedConfig.isSchemaRegistrySuppressCertPathValidation()) { SSLSocketFactory sslSocketFactory = SslSocketFactoryCreator.buildSSlSocketFactory(selectedConfig, configHandler); schemaRegistryRestService.setSslSocketFactory(sslSocketFactory); } @@ -84,14 +84,14 @@ public void setup(ClusterConfig selectedConfig, ConfigHandler configHandler) { versionComboBox.getSelectionModel().select(versionComboBox.getItems().size() - 1); } } catch (Exception e) { - ErrorAlert.show(e, getWindow()); + ErrorAlert.show(e); } }); subjectListView.setItems(FXCollections.observableArrayList(schemaRegistryRestService.getAllSubjects())); } catch (Exception e) { - ErrorAlert.show(e, getWindow()); + ErrorAlert.show(e); } } diff --git a/src/main/java/at/esque/kafka/cluster/ClusterConfig.java b/src/main/java/at/esque/kafka/cluster/ClusterConfig.java index 9bf32fd..0c4cb99 100644 --- a/src/main/java/at/esque/kafka/cluster/ClusterConfig.java +++ b/src/main/java/at/esque/kafka/cluster/ClusterConfig.java @@ -16,6 +16,7 @@ public class ClusterConfig { private StringProperty schemaRegistryBasicAuthUserInfo = new SimpleStringProperty(); private BooleanProperty schemaRegistryUseSsl = new SimpleBooleanProperty(); private BooleanProperty sslEnabled = new SimpleBooleanProperty(); + private BooleanProperty certPathValidationSuppressed = new SimpleBooleanProperty(); private StringProperty keyStoreLocation = new SimpleStringProperty(); private StringProperty keyStorePassword = new SimpleStringProperty(); private StringProperty trustStoreLocation = new SimpleStringProperty(); @@ -43,6 +44,7 @@ public void update(ClusterConfig existingConfig) { this.setSchemaRegistry(existingConfig.getSchemaRegistry()); this.setSchemaRegistryBasicAuthUserInfo(existingConfig.getSchemaRegistryBasicAuthUserInfo()); this.setSchemaRegistryUseSsl(existingConfig.isSchemaRegistryUseSsl()); + this.setSchemaRegistrySuppressCertPathValidation(existingConfig.isSchemaRegistrySuppressCertPathValidation()); this.setSslEnabled(existingConfig.isSslEnabled()); this.setKeyStoreLocation(existingConfig.getKeyStoreLocation()); this.setKeyStorePassword(existingConfig.getKeyStorePassword()); @@ -111,6 +113,18 @@ public void setSslEnabled(boolean sslEnabled) { this.sslEnabled.set(sslEnabled); } + @JsonProperty("certPathValidationSuppressed") + public boolean isSchemaRegistrySuppressCertPathValidation() { + return certPathValidationSuppressed.get(); + } + public BooleanProperty suppressCertPathValidation() { + return certPathValidationSuppressed; + } + + public void setSchemaRegistrySuppressCertPathValidation(boolean suppressCertPathValidation) { + this.certPathValidationSuppressed.set(suppressCertPathValidation); + } + @JsonProperty("keyStoreLocation") public String getKeyStoreLocation() { return keyStoreLocation.get(); diff --git a/src/main/java/at/esque/kafka/cluster/SslSocketFactoryCreator.java b/src/main/java/at/esque/kafka/cluster/SslSocketFactoryCreator.java index 7b299dc..75ea5fc 100644 --- a/src/main/java/at/esque/kafka/cluster/SslSocketFactoryCreator.java +++ b/src/main/java/at/esque/kafka/cluster/SslSocketFactoryCreator.java @@ -3,10 +3,7 @@ import at.esque.kafka.handlers.ConfigHandler; import org.apache.kafka.common.config.SslConfigs; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.*; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyManagementException; @@ -15,6 +12,7 @@ import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; import java.util.Map; public class SslSocketFactoryCreator { @@ -22,27 +20,48 @@ public class SslSocketFactoryCreator { private SslSocketFactoryCreator() { } + private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{ + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + public static SSLSocketFactory buildSSlSocketFactory(ClusterConfig clusterConfig, ConfigHandler configHandler) { try { KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); Map sslProperties = configHandler.getSslProperties(clusterConfig); - ks.load(new FileInputStream(sslProperties.get(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG)), sslProperties.get(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG).toCharArray()); - KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType()); - ts.load(new FileInputStream(sslProperties.get(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG)), sslProperties.get(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG).toCharArray()); + SSLContext sc = SSLContext.getInstance("TLSv1.2"); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, sslProperties.get(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG).toCharArray()); + if (clusterConfig.isSchemaRegistrySuppressCertPathValidation()) { + sc.init(null, UNQUESTIONING_TRUST_MANAGER, null); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ts); + } + if (clusterConfig.isSchemaRegistryUseSsl()) { + ks.load(new FileInputStream(sslProperties.get(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG)), sslProperties.get(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG).toCharArray()); - SSLContext sc = SSLContext.getInstance("TLSv1.2"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType()); + ts.load(new FileInputStream(sslProperties.get(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG)), sslProperties.get(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG).toCharArray()); - return sc.getSocketFactory(); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, sslProperties.get(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG).toCharArray()); - } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException e) { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ts); + + + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + + return sc.getSocketFactory(); + } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | + UnrecoverableKeyException | KeyManagementException e) { at.esque.kafka.alerts.ErrorAlert.show(e); return null; } diff --git a/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java b/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java index 70b5cdb..61f1431 100644 --- a/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java +++ b/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java @@ -33,6 +33,7 @@ public class ClusterConfigDialog { public static final String LABEL_KAFKA_CONNECT_BASIC_AUTH_USER = "Kafka Connect Basic Auth User"; public static final String LABEL_KAFKA_CONNECT_BASIC_AUTH_PASSWORD = "Kafka Connect Basic Auth Password"; public static final String LABEL_USE_SSL_CONFIGURATION = "use SSL Configuration"; + public static final String LABEL_SUPPRESS_CERT_PATH_VALIDATION = "suppress Cert Path Validation"; public static final String LABEL_SUPPRESS_SSL_ENDPOINT_IDENTIFICATION = "no SSL Endpoint Identification"; private ClusterConfigDialog(){} @@ -80,7 +81,11 @@ public static Optional show(ClusterConfig existingConfig) { Field.ofBooleanType(copy.isSchemaRegistryUseSsl()) .label(LABEL_USE_SSL_CONFIGURATION) .tooltip(LABEL_USE_SSL_CONFIGURATION) - .bind(copy.schemaRegistryUseSslProperty()) + .bind(copy.schemaRegistryUseSslProperty()), + Field.ofBooleanType(copy.isSchemaRegistrySuppressCertPathValidation()) + .label(LABEL_SUPPRESS_CERT_PATH_VALIDATION) + .tooltip(LABEL_SUPPRESS_CERT_PATH_VALIDATION) + .bind(copy.suppressCertPathValidation()) ), Group.of( Field.ofStringType(copy.getkafkaConnectUrl()==null?"":copy.getkafkaConnectUrl())