From f7e77224ec19dda3edf98dd782f11f2d5bf978d9 Mon Sep 17 00:00:00 2001 From: Rob Rudin Date: Sun, 29 Dec 2019 14:49:19 -0500 Subject: [PATCH] #392 Can now create SSL connections using default keystore Hacking around asdfasdf adsf more afasfd asdf --- .../com/marklogic/appdeployer/AppConfig.java | 106 +++++++++++++++--- .../appdeployer/DefaultAppConfigFactory.java | 31 +++++ .../mgmt/DefaultManageConfigFactory.java | 15 +++ .../mgmt/admin/DefaultAdminConfigFactory.java | 15 +++ .../com/marklogic/rest/util/RestConfig.java | 29 +++++ .../rest/util/configurer/SslConfigurer.java | 99 ++++++++-------- .../DefaultAppConfigFactoryTest.java | 26 +++++ .../mgmt/DefaultManageConfigFactoryTest.java | 15 +++ .../admin/DefaultAdminConfigFactoryTest.java | 15 +++ .../rest/util/RestTemplateUtilTest.java | 102 ++++++++++------- 10 files changed, 354 insertions(+), 99 deletions(-) diff --git a/src/main/java/com/marklogic/appdeployer/AppConfig.java b/src/main/java/com/marklogic/appdeployer/AppConfig.java index 5abd7fdd..00874886 100644 --- a/src/main/java/com/marklogic/appdeployer/AppConfig.java +++ b/src/main/java/com/marklogic/appdeployer/AppConfig.java @@ -12,10 +12,12 @@ import com.marklogic.client.ext.SecurityContextType; import com.marklogic.client.ext.modulesloader.impl.PropertiesModuleManager; import com.marklogic.client.ext.modulesloader.ssl.SimpleX509TrustManager; +import com.marklogic.client.ext.ssl.SslUtil; import com.marklogic.client.ext.tokenreplacer.DefaultTokenReplacer; import com.marklogic.client.ext.tokenreplacer.PropertiesSource; import com.marklogic.client.ext.tokenreplacer.RoxyTokenReplacer; import com.marklogic.client.ext.tokenreplacer.TokenReplacer; +import org.springframework.util.StringUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.X509TrustManager; @@ -92,7 +94,11 @@ public class AppConfig { private String restCertPassword; private String restExternalName; private X509TrustManager restTrustManager; - private Integer restPort = DEFAULT_PORT; + private boolean restUseDefaultKeystore; + private String restSslProtocol; + private String restTrustManagementAlgorithm; + + private Integer restPort = DEFAULT_PORT; private Integer testRestPort; // Connection info for using the App Services client REST API - e.g. to load non-REST API modules @@ -107,6 +113,9 @@ public class AppConfig { private String appServicesCertPassword; private String appServicesExternalName; private X509TrustManager appServicesTrustManager; + private boolean appServicesUseDefaultKeystore; + private String appServicesSslProtocol; + private String appServicesTrustManagementAlgorithm; // These can all be set to override the default names that are generated off of the "name" attribute. private String groupName = DEFAULT_GROUP; @@ -364,15 +373,24 @@ public DatabaseClient newTestDatabaseClient() { } public DatabaseClientConfig newRestDatabaseClientConfig(int port) { - DatabaseClientConfig config = new DatabaseClientConfig(getHost(), port, getRestAdminUsername(), getRestAdminPassword()); - config.setCertFile(getRestCertFile()); - config.setCertPassword(getRestCertPassword()); + DatabaseClientConfig config = new DatabaseClientConfig(host, port, restAdminUsername, restAdminPassword); + config.setCertFile(restCertFile); + config.setCertPassword(restCertPassword); config.setConnectionType(restConnectionType); - config.setExternalName(getRestExternalName()); + config.setExternalName(restExternalName); config.setSecurityContextType(restSecurityContextType); - config.setSslContext(getRestSslContext()); - config.setSslHostnameVerifier(getRestSslHostnameVerifier()); - config.setTrustManager(restTrustManager); + + if (restUseDefaultKeystore) { + config.setSslProtocol(StringUtils.hasText(restSslProtocol) ? restSslProtocol : SslUtil.DEFAULT_SSL_PROTOCOL); + config.setTrustManagementAlgorithm(restTrustManagementAlgorithm); + config.setSslHostnameVerifier(restSslHostnameVerifier != null ? restSslHostnameVerifier : SSLHostnameVerifier.ANY); + } + else { + config.setSslContext(restSslContext); + config.setTrustManager(restTrustManager); + config.setSslHostnameVerifier(restSslHostnameVerifier); + } + return config; } @@ -394,16 +412,25 @@ public DatabaseClient newSchemasDatabaseClient() { } public DatabaseClient newAppServicesDatabaseClient(String databaseName) { - DatabaseClientConfig config = new DatabaseClientConfig(getHost(), getAppServicesPort(), getAppServicesUsername(), getAppServicesPassword()); - config.setCertFile(getAppServicesCertFile()); - config.setCertPassword(getAppServicesCertPassword()); + DatabaseClientConfig config = new DatabaseClientConfig(host, appServicesPort, appServicesUsername, appServicesPassword); + config.setCertFile(appServicesCertFile); + config.setCertPassword(appServicesCertPassword); config.setConnectionType(appServicesConnectionType); config.setDatabase(databaseName); - config.setExternalName(getAppServicesExternalName()); + config.setExternalName(appServicesExternalName); config.setSecurityContextType(appServicesSecurityContextType); - config.setSslContext(getAppServicesSslContext()); - config.setSslHostnameVerifier(getAppServicesSslHostnameVerifier()); - config.setTrustManager(appServicesTrustManager); + + if (appServicesUseDefaultKeystore) { + config.setSslProtocol(StringUtils.hasText(appServicesSslProtocol) ? appServicesSslProtocol : SslUtil.DEFAULT_SSL_PROTOCOL); + config.setTrustManagementAlgorithm(appServicesTrustManagementAlgorithm); + config.setSslHostnameVerifier(appServicesSslHostnameVerifier != null ? appServicesSslHostnameVerifier : SSLHostnameVerifier.ANY); + } + else { + config.setSslContext(appServicesSslContext); + config.setTrustManager(appServicesTrustManager); + config.setSslHostnameVerifier(appServicesSslHostnameVerifier); + } + return configuredDatabaseClientFactory.newDatabaseClient(config); } @@ -1424,4 +1451,53 @@ public void setDeployAmpsWithCma(boolean b) { getCmaConfig().setDeployAmps(b); } // End of methods still used by DHF 4.3.x + + + public boolean isRestUseDefaultKeystore() { + return restUseDefaultKeystore; + } + + public void setRestUseDefaultKeystore(boolean restUseDefaultKeystore) { + this.restUseDefaultKeystore = restUseDefaultKeystore; + } + + public String getRestSslProtocol() { + return restSslProtocol; + } + + public void setRestSslProtocol(String restSslProtocol) { + this.restSslProtocol = restSslProtocol; + } + + public String getRestTrustManagementAlgorithm() { + return restTrustManagementAlgorithm; + } + + public void setRestTrustManagementAlgorithm(String restTrustManagementAlgorithm) { + this.restTrustManagementAlgorithm = restTrustManagementAlgorithm; + } + + public boolean isAppServicesUseDefaultKeystore() { + return appServicesUseDefaultKeystore; + } + + public void setAppServicesUseDefaultKeystore(boolean appServicesUseDefaultKeystore) { + this.appServicesUseDefaultKeystore = appServicesUseDefaultKeystore; + } + + public String getAppServicesSslProtocol() { + return appServicesSslProtocol; + } + + public void setAppServicesSslProtocol(String appServicesSslProtocol) { + this.appServicesSslProtocol = appServicesSslProtocol; + } + + public String getAppServicesTrustManagementAlgorithm() { + return appServicesTrustManagementAlgorithm; + } + + public void setAppServicesTrustManagementAlgorithm(String appServicesTrustManagementAlgorithm) { + this.appServicesTrustManagementAlgorithm = appServicesTrustManagementAlgorithm; + } } diff --git a/src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java b/src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java index 2d236730..fc21325c 100644 --- a/src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java +++ b/src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java @@ -238,6 +238,21 @@ public void initialize() { } }); + propertyConsumerMap.put("mlAppServicesSslProtocol", (config, prop) -> { + logger.info("Using SSL protocol for App-Services server: " + prop); + config.setAppServicesSslProtocol(prop); + }); + + propertyConsumerMap.put("mlAppServicesUseDefaultKeystore", (config, prop) -> { + logger.info("Using default JVM keystore for SSL for App-Services server: " + prop); + config.setAppServicesUseDefaultKeystore(Boolean.parseBoolean(prop)); + }); + + propertyConsumerMap.put("mlAppServicesTrustManagementAlgorithm", (config, prop) -> { + logger.info("Using trust management algorithm for SSL for App-Services server: " + prop); + config.setAppServicesTrustManagementAlgorithm(prop); + }); + /** * Set this to true to prevent creating a REST API server by default. */ @@ -309,6 +324,22 @@ public void initialize() { } }); + propertyConsumerMap.put("mlRestSslProtocol", (config, prop) -> { + logger.info("Using SSL protocol for client REST API server: " + prop); + config.setRestSslProtocol(prop); + }); + + propertyConsumerMap.put("mlRestUseDefaultKeystore", (config, prop) -> { + logger.info("Using default JVM keystore for SSL for client REST API server: " + prop); + config.setRestUseDefaultKeystore(Boolean.parseBoolean(prop)); + }); + + propertyConsumerMap.put("mlRestTrustManagementAlgorithm", (config, prop) -> { + logger.info("Using trust management algorithm for SSL for client REST API server: " + prop); + config.setRestTrustManagementAlgorithm(prop); + }); + + /** * mlUsername and mlPassword are the default username/password for connecting to the app's REST server (if one * exists) and to App-Services on 8000. These are processed before the other username/password properties so that diff --git a/src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java b/src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java index d32030ba..50debf96 100644 --- a/src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java +++ b/src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java @@ -82,6 +82,21 @@ public void initialize() { config.setConfigureSimpleSsl(Boolean.parseBoolean(prop)); }); + propertyConsumerMap.put("mlManageSslProtocol", (config, prop) -> { + logger.info("Using SSL protocol for Manage app server: " + prop); + config.setSslProtocol(prop); + }); + + propertyConsumerMap.put("mlManageUseDefaultKeystore", (config, prop) -> { + logger.info("Using default JVM keystore for SSL for Manage app server: " + prop); + config.setUseDefaultKeystore(Boolean.parseBoolean(prop)); + }); + + propertyConsumerMap.put("mlManageTrustManagementAlgorithm", (config, prop) -> { + logger.info("Using trust management algorithm for SSL for Manage app server: " + prop); + config.setTrustManagementAlgorithm(prop); + }); + propertyConsumerMap.put("mlManageCleanJsonPayloads", (config, prop) -> { logger.info("Cleaning Management API JSON payloads: " + prop); config.setCleanJsonPayloads(Boolean.parseBoolean(prop)); diff --git a/src/main/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactory.java b/src/main/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactory.java index 707b0647..531034d5 100644 --- a/src/main/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactory.java +++ b/src/main/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactory.java @@ -78,6 +78,21 @@ public void initialize() { logger.info("Use simple SSL for Admin interface: " + prop); config.setConfigureSimpleSsl(Boolean.parseBoolean(prop)); }); + + propertyConsumerMap.put("mlAdminSslProtocol", (config, prop) -> { + logger.info("Using SSL protocol for Admin app server: " + prop); + config.setSslProtocol(prop); + }); + + propertyConsumerMap.put("mlAdminUseDefaultKeystore", (config, prop) -> { + logger.info("Using default JVM keystore for SSL for Admin app server: " + prop); + config.setUseDefaultKeystore(Boolean.parseBoolean(prop)); + }); + + propertyConsumerMap.put("mlAdminTrustManagementAlgorithm", (config, prop) -> { + logger.info("Using trust management algorithm for SSL for Admin app server: " + prop); + config.setTrustManagementAlgorithm(prop); + }); } @Override diff --git a/src/main/java/com/marklogic/rest/util/RestConfig.java b/src/main/java/com/marklogic/rest/util/RestConfig.java index 2b9f2d7f..4b4ec470 100644 --- a/src/main/java/com/marklogic/rest/util/RestConfig.java +++ b/src/main/java/com/marklogic/rest/util/RestConfig.java @@ -13,7 +13,12 @@ public class RestConfig { private String username; private String password; private String scheme = "http"; + private boolean configureSimpleSsl; + private boolean useDefaultKeystore; + private String sslProtocol; + private String trustManagementAlgorithm; + private SSLContext sslContext; private X509HostnameVerifier hostnameVerifier; @@ -116,4 +121,28 @@ public X509HostnameVerifier getHostnameVerifier() { public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; } + + public String getSslProtocol() { + return sslProtocol; + } + + public void setSslProtocol(String sslProtocol) { + this.sslProtocol = sslProtocol; + } + + public String getTrustManagementAlgorithm() { + return trustManagementAlgorithm; + } + + public void setTrustManagementAlgorithm(String trustManagementAlgorithm) { + this.trustManagementAlgorithm = trustManagementAlgorithm; + } + + public boolean isUseDefaultKeystore() { + return useDefaultKeystore; + } + + public void setUseDefaultKeystore(boolean useDefaultKeystore) { + this.useDefaultKeystore = useDefaultKeystore; + } } diff --git a/src/main/java/com/marklogic/rest/util/configurer/SslConfigurer.java b/src/main/java/com/marklogic/rest/util/configurer/SslConfigurer.java index d064c54d..c2d7556c 100644 --- a/src/main/java/com/marklogic/rest/util/configurer/SslConfigurer.java +++ b/src/main/java/com/marklogic/rest/util/configurer/SslConfigurer.java @@ -1,76 +1,87 @@ package com.marklogic.rest.util.configurer; import com.marklogic.client.ext.helper.LoggingObject; +import com.marklogic.client.ext.ssl.SslUtil; import com.marklogic.rest.util.HttpClientBuilderConfigurer; import com.marklogic.rest.util.RestConfig; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; import org.apache.http.conn.ssl.SSLContextBuilder; -import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.client.HttpClientBuilder; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; -import java.security.cert.X509Certificate; public class SslConfigurer extends LoggingObject implements HttpClientBuilderConfigurer { + /** + * First checks for a custom SSLContext; then checks to see if the default keystore should be used; then checks to + * see if a simple "trust everything" approach should be used. + * + * @param config + * @param httpClientBuilder + * @return + */ @Override public HttpClientBuilder configureHttpClientBuilder(RestConfig config, HttpClientBuilder httpClientBuilder) { - if (config.isConfigureSimpleSsl()) { - if (logger.isInfoEnabled()) { - logger.info("Configuring simple SSL approach for connecting to: " + config.getBaseUrl()); - } - configureSimpleSsl(httpClientBuilder); - } - + SSLContext sslContext = null; if (config.getSslContext() != null) { if (logger.isInfoEnabled()) { logger.info("Using custom SSLContext for connecting to: " + config.getBaseUrl()); } - httpClientBuilder.setSslcontext(config.getSslContext()); + sslContext = config.getSslContext(); + } else if (config.isUseDefaultKeystore()) { + sslContext = buildSslContextViaTrustManagerFactory(config); + } else if (config.isConfigureSimpleSsl()) { + sslContext = buildSimpleSslContext(config); } - if (config.getHostnameVerifier() != null) { - if (logger.isInfoEnabled()) { - logger.info("Using custom X509HostnameVerifier for connecting to: " + config.getBaseUrl()); + if (sslContext != null) { + httpClientBuilder.setSslcontext(sslContext); + + if (config.getHostnameVerifier() != null) { + if (logger.isInfoEnabled()) { + logger.info("Using custom X509HostnameVerifier for connecting to: " + config.getBaseUrl()); + } + httpClientBuilder.setHostnameVerifier(config.getHostnameVerifier()); + } else { + if (logger.isInfoEnabled()) { + logger.info("Using 'allow all' X509HostnameVerifier for connecting to: " + config.getBaseUrl()); + } + httpClientBuilder.setHostnameVerifier(new AllowAllHostnameVerifier()); } - httpClientBuilder.setHostnameVerifier(config.getHostnameVerifier()); } return httpClientBuilder; } - protected void configureSimpleSsl(HttpClientBuilder httpClientBuilder) { - try { - SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { - @Override - public boolean isTrusted(X509Certificate[] chain, String authType) { - return true; - } - }).build(); - httpClientBuilder.setSslcontext(sslContext); - } catch (Exception ex) { - throw new RuntimeException("Unable to configure simple SSLContext, cause: " + ex.getMessage(), ex); + protected SSLContext buildSslContextViaTrustManagerFactory(RestConfig config) { + final String protocol = determineProtocol(config); + final String algorithm = config.getTrustManagementAlgorithm(); + if (logger.isInfoEnabled()) { + logger.info("Using default keystore with SSL protocol " + protocol + " for connecting to: " + config.getBaseUrl()); } + return SslUtil.configureUsingTrustManagerFactory(protocol, algorithm).getSslContext(); + } - httpClientBuilder.setHostnameVerifier(new X509HostnameVerifier() { - @Override - public void verify(String host, SSLSocket ssl) { - } - - @Override - public void verify(String host, X509Certificate cert) { - } + protected SSLContext buildSimpleSslContext(RestConfig config) { + final String protocol = determineProtocol(config); - @Override - public void verify(String host, String[] cns, String[] subjectAlts) { - } + SSLContextBuilder builder = new SSLContextBuilder().useProtocol(protocol); + if (logger.isInfoEnabled()) { + logger.info("Configuring simple SSL approach with protocol " + protocol + " for connecting to: " + config.getBaseUrl()); + } + try { + return builder.loadTrustMaterial(null, (chain, authType) -> true).build(); + } catch (Exception ex) { + throw new RuntimeException("Unable to configure simple SSLContext for connecting to: " + config.getBaseUrl() + ", cause: " + ex.getMessage(), ex); + } + } - @Override - public boolean verify(String s, SSLSession sslSession) { - return true; - } - }); + protected String determineProtocol(RestConfig config) { + String protocol = config.getSslProtocol(); + if (StringUtils.isEmpty(protocol)) { + protocol = SslUtil.DEFAULT_SSL_PROTOCOL; + } + return protocol; } } diff --git a/src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java b/src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java index 10006c84..2e5f5a32 100644 --- a/src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java +++ b/src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java @@ -636,4 +636,30 @@ public void restSimpleSsl() { config = new DefaultAppConfigFactory(new SimplePropertySource()).newAppConfig(); assertNull(config.getRestSslContext()); } + + @Test + public void restUseDefaultKeystore() { + AppConfig config = new DefaultAppConfigFactory(new SimplePropertySource( + "mlRestUseDefaultKeystore", "true", + "mlRestSslProtocol", "SSLv3", + "mlRestTrustManagementAlgorithm", "PKIX" + )).newAppConfig(); + + assertTrue(config.isRestUseDefaultKeystore()); + assertEquals("SSLv3", config.getRestSslProtocol()); + assertEquals("PKIX", config.getRestTrustManagementAlgorithm()); + } + + @Test + public void appServicesUseDefaultKeystore() { + AppConfig config = new DefaultAppConfigFactory(new SimplePropertySource( + "mlAppServicesUseDefaultKeystore", "true", + "mlAppServicesSslProtocol", "SSLv3", + "mlAppServicesTrustManagementAlgorithm", "PKIX" + )).newAppConfig(); + + assertTrue(config.isAppServicesUseDefaultKeystore()); + assertEquals("SSLv3", config.getAppServicesSslProtocol()); + assertEquals("PKIX", config.getAppServicesTrustManagementAlgorithm()); + } } diff --git a/src/test/java/com/marklogic/mgmt/DefaultManageConfigFactoryTest.java b/src/test/java/com/marklogic/mgmt/DefaultManageConfigFactoryTest.java index 8c3782e5..08dd7a68 100644 --- a/src/test/java/com/marklogic/mgmt/DefaultManageConfigFactoryTest.java +++ b/src/test/java/com/marklogic/mgmt/DefaultManageConfigFactoryTest.java @@ -70,6 +70,21 @@ public void mlAdminUsername() { assertEquals("bobpwd", config.getSecurityPassword()); } + @Test + public void sslProperties() { + ManageConfig config = configure( + "mlManageSimpleSsl", "true", + "mlManageSslProtocol", "TLSv1.2", + "mlManageUseDefaultKeystore", "true", + "mlManageTrustManagementAlgorithm", "PKIX" + ); + + assertTrue(config.isConfigureSimpleSsl()); + assertEquals("TLSv1.2", config.getSslProtocol()); + assertTrue(config.isUseDefaultKeystore()); + assertEquals("PKIX", config.getTrustManagementAlgorithm()); + } + @Test public void mlHost() { ManageConfig config = configure("mlHost", "host1"); diff --git a/src/test/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactoryTest.java b/src/test/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactoryTest.java index b8815950..8593651d 100644 --- a/src/test/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactoryTest.java +++ b/src/test/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactoryTest.java @@ -40,6 +40,21 @@ public void mlManageHost() { assertEquals("host2", config.getHost()); } + @Test + public void sslProperties() { + AdminConfig config = configure( + "mlAdminSimpleSsl", "true", + "mlAdminSslProtocol", "TLSv1.2", + "mlAdminUseDefaultKeystore", "true", + "mlAdminTrustManagementAlgorithm", "PKIX" + ); + + assertTrue(config.isConfigureSimpleSsl()); + assertEquals("TLSv1.2", config.getSslProtocol()); + assertTrue(config.isUseDefaultKeystore()); + assertEquals("PKIX", config.getTrustManagementAlgorithm()); + } + private AdminConfig configure(String... properties) { return new DefaultAdminConfigFactory(new SimplePropertySource(properties)).newAdminConfig(); } diff --git a/src/test/java/com/marklogic/rest/util/RestTemplateUtilTest.java b/src/test/java/com/marklogic/rest/util/RestTemplateUtilTest.java index 347dd273..04a65e8a 100644 --- a/src/test/java/com/marklogic/rest/util/RestTemplateUtilTest.java +++ b/src/test/java/com/marklogic/rest/util/RestTemplateUtilTest.java @@ -1,21 +1,24 @@ package com.marklogic.rest.util; -import com.marklogic.mgmt.AbstractMgmtTest; +import com.marklogic.junit.BaseTestHelper; import com.marklogic.mgmt.ManageClient; -import com.marklogic.rest.util.RestTemplateUtil; +import com.marklogic.mgmt.ManageConfig; +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; import org.apache.http.conn.ssl.SSLContextBuilder; -import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.conn.ssl.X509HostnameVerifier; import org.junit.Test; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; -import java.security.cert.X509Certificate; -public class RestTemplateUtilTest extends AbstractMgmtTest { +/** + * Many of these tests are just smoke tests that can be used to inspect logging as well. Ideally, they can soon depend + * on the Manage server being configured to use SSL. Although testing the use of the default keystore would likely + * still be out of scope due to the difficulty of using a certificate signed by an authority that's trusted by the + * default keystore. + */ +public class RestTemplateUtilTest extends BaseTestHelper { private boolean configurerInvoked = false; + private ManageConfig manageConfig = new ManageConfig(); @Test public void configurerList() { @@ -32,49 +35,68 @@ public void configurerList() { assertTrue(configurerInvoked); } - /** - * Just a smoke test to inspect the logging. - */ @Test public void configureSimpleSsl() { manageConfig.setConfigureSimpleSsl(true); new ManageClient(manageConfig); } - /** - * Another smoke test to inspect logging. - */ + @Test + public void simpleSslWithCustomProtocol() { + manageConfig.setConfigureSimpleSsl(true); + manageConfig.setSslProtocol("SSLv3"); + new ManageClient(manageConfig); + } + + @Test + public void simpleSslWithInvalidProtocol() { + manageConfig.setConfigureSimpleSsl(true); + manageConfig.setSslProtocol("invalid"); + try { + new ManageClient(manageConfig); + fail("Expected failure due to invalid protocol"); + } catch (Exception ex) { + logger.info("Caught expected exception: " + ex.getMessage()); + } + } + @Test public void customSslContextAndHostnameVerifier() throws Exception { - SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { - @Override - public boolean isTrusted(X509Certificate[] chain, String authType) { - return true; - } - }).build(); - - X509HostnameVerifier verifier = new X509HostnameVerifier() { - @Override - public void verify(String host, SSLSocket ssl) { - } - - @Override - public void verify(String host, X509Certificate cert) { - } - - @Override - public void verify(String host, String[] cns, String[] subjectAlts) { - } - - @Override - public boolean verify(String s, SSLSession sslSession) { - return false; - } - }; + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build(); manageConfig.setSslContext(sslContext); - manageConfig.setHostnameVerifier(verifier); + manageConfig.setHostnameVerifier(new AllowAllHostnameVerifier()); new ManageClient(manageConfig); } + + @Test + public void useDefaultKeystore() { + manageConfig.setUseDefaultKeystore(true); + new ManageClient(manageConfig); + } + + @Test + public void defaultKeystoreWithInvalidProtocol() { + manageConfig.setUseDefaultKeystore(true); + manageConfig.setSslProtocol("invalid"); + try { + new ManageClient(manageConfig); + fail("Expected failure due to invalid protocol"); + } catch (Exception ex) { + logger.info("Caught expected exception: " + ex.getMessage()); + } + } + + @Test + public void defaultKeystoreWithInvalidAlgorithm() { + manageConfig.setUseDefaultKeystore(true); + manageConfig.setTrustManagementAlgorithm("invalid"); + try { + new ManageClient(manageConfig); + fail("Expected failure due to invalid algorithm"); + } catch (Exception ex) { + logger.info("Caught expected exception: " + ex.getMessage()); + } + } }