From 25960adc4d294efa92957e5da32cffb12028660c Mon Sep 17 00:00:00 2001 From: John Blum Date: Thu, 17 Oct 2019 15:50:26 -0700 Subject: [PATCH] Add auto-configuration support for TLS using SSL when deploying Spring Boot ClientCache applications to PCF using PCC that requires secure Sockets. The TLS/SSL auto-configuration enables and configures the use of the SSL default context provided by the JRE, which the ClientCache instance uses to obtain the required CERT necessary when creating SSL Sockets between the client and PCC servers. Resolves gh-61. --- .../ClientSecurityAutoConfiguration.java | 14 + ...entSecurityAutoConfigurationUnitTests.java | 43 ++- .../geode/core/env/VcapPropertySource.java | 8 + .../core/env/support/CloudCacheService.java | 27 ++ .../core/env/VcapPropertySourceUnitTests.java | 252 +++++++++++------- .../support/CloudCacheServiceUnitTests.java | 41 ++- 6 files changed, 276 insertions(+), 109 deletions(-) diff --git a/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.java b/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.java index 26a70aed..4873fd0f 100644 --- a/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.java +++ b/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.java @@ -62,6 +62,8 @@ import org.springframework.util.StringUtils; * @see org.springframework.boot.SpringApplication * @see org.springframework.boot.autoconfigure.AutoConfigureBefore * @see org.springframework.boot.autoconfigure.EnableAutoConfiguration + * @see org.springframework.boot.autoconfigure.condition.AllNestedConditions + * @see org.springframework.boot.autoconfigure.condition.AnyNestedCondition * @see org.springframework.boot.autoconfigure.condition.ConditionalOnClass * @see org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform * @see org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean @@ -116,6 +118,9 @@ public class ClientSecurityAutoConfiguration { private static final String SECURITY_PASSWORD_PROPERTY = AutoConfiguredAuthenticationInitializer.SDG_SECURITY_PASSWORD_PROPERTY; + private static final String SSL_USE_DEFAULT_CONTEXT_PROPERTY = + "spring.data.gemfire.security.ssl.use-default-context"; + private static final String VCAP_PROPERTY_SOURCE_NAME = "vcap"; public static class AutoConfiguredCloudSecurityEnvironmentPostProcessor implements EnvironmentPostProcessor { @@ -212,6 +217,14 @@ public class ClientSecurityAutoConfiguration { }); } + private void configureSsl(Environment environment, VcapPropertySource vcapPropertySource, + CloudCacheService cloudCacheService, Properties cloudCacheProperties) { + + if (cloudCacheService.isTlsEnabled()) { + cloudCacheProperties.setProperty(SSL_USE_DEFAULT_CONTEXT_PROPERTY, Boolean.TRUE.toString()); + } + } + public void configureSecurityContext(ConfigurableEnvironment environment) { String cloudcacheServiceInstanceName = environment.getProperty(CLOUD_CACHE_SERVICE_INSTANCE_NAME_PROPERTY); @@ -228,6 +241,7 @@ public class ClientSecurityAutoConfiguration { configureAuthentication(environment, vcapPropertySource, cloudCacheService, cloudCacheProperties); configureLocators(environment, vcapPropertySource, cloudCacheService, cloudCacheProperties); configureManagementRestApiAccess(environment, vcapPropertySource, cloudCacheService, cloudCacheProperties); + configureSsl(environment, vcapPropertySource, cloudCacheService, cloudCacheProperties); environment.getPropertySources() .addLast(newPropertySource(CLOUD_CACHE_PROPERTY_SOURCE_NAME, cloudCacheProperties)); diff --git a/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/security/auth/ClientSecurityAutoConfigurationUnitTests.java b/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/security/auth/ClientSecurityAutoConfigurationUnitTests.java index 65c4aee5..67f4271b 100644 --- a/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/security/auth/ClientSecurityAutoConfigurationUnitTests.java +++ b/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/security/auth/ClientSecurityAutoConfigurationUnitTests.java @@ -235,6 +235,7 @@ public class ClientSecurityAutoConfigurationUnitTests { assertThat(propertySource.getName()).isEqualTo("boot.data.gemfire.cloudcache"); assertThat(propertySource.getProperty("spring.data.gemfire.security.username")).isEqualTo("Master"); assertThat(propertySource.getProperty("spring.data.gemfire.security.password")).isEqualTo("p@$$w0rd"); + assertThat(propertySource.containsProperty("spring.data.gemfire.security.ssl.use-default-context")).isFalse(); assertThat(propertySource.getProperty("spring.data.gemfire.pool.locators")) .isEqualTo("boombox[10334],skullbox[10334]"); assertThat(propertySource.getProperty("spring.data.gemfire.management.use-http")).isEqualTo("true"); @@ -251,8 +252,6 @@ public class ClientSecurityAutoConfigurationUnitTests { when(mockEnvironment.containsProperty("spring.data.gemfire.security.username")).thenReturn(true); when(mockEnvironment.containsProperty("spring.data.gemfire.security.password")).thenReturn(true); - MutablePropertySources propertySources = new MutablePropertySources(); - Properties vcapProperties = new Properties(); vcapProperties.setProperty("vcap.application.name", "TestApp"); @@ -269,6 +268,8 @@ public class ClientSecurityAutoConfigurationUnitTests { PropertySource vcapPropertySource = new PropertiesPropertySource("vcap", vcapProperties); + MutablePropertySources propertySources = new MutablePropertySources(); + propertySources.addFirst(vcapPropertySource); when(mockEnvironment.getPropertySources()).thenReturn(propertySources); @@ -288,6 +289,7 @@ public class ClientSecurityAutoConfigurationUnitTests { assertThat(propertySource.getName()).isEqualTo("boot.data.gemfire.cloudcache"); assertThat(propertySource.containsProperty("spring.data.gemfire.security.username")).isFalse(); assertThat(propertySource.containsProperty("spring.data.gemfire.security.password")).isFalse(); + assertThat(propertySource.containsProperty("spring.data.gemfire.security.ssl.use-default-context")).isFalse(); assertThat(propertySource.getProperty("spring.data.gemfire.pool.locators")) .isEqualTo("boombox[10334],skullbox[10334]"); assertThat(propertySource.containsProperty("spring.data.gemfire.management.use-http")).isFalse(); @@ -296,6 +298,43 @@ public class ClientSecurityAutoConfigurationUnitTests { assertThat(propertySource.containsProperty("spring.data.gemfire.management.http.port")).isFalse(); } + @Test + public void configuresSecurityContextWithTlsUsingSsl() { + + ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class); + + Properties vcapProperties = new Properties(); + + vcapProperties.setProperty("vcap.application.name", "TestApp"); + vcapProperties.setProperty("vcap.application.uris", "test-app.apps.cloud.skullbox.com"); + vcapProperties.setProperty("vcap.services.test-pcc.credentials.tls-enabled", "true"); + vcapProperties.setProperty("vcap.services.test-pcc.tags", "junk,gemfire,mock,cloudcache,test"); + + PropertySource vcapPropertySource = new PropertiesPropertySource("vcap", vcapProperties); + + MutablePropertySources propertySources = new MutablePropertySources(); + + propertySources.addFirst(vcapPropertySource); + + when(mockEnvironment.getPropertySources()).thenReturn(propertySources); + + AutoConfiguredCloudSecurityEnvironmentPostProcessor environmentPostProcessor = + spy(new AutoConfiguredCloudSecurityEnvironmentPostProcessor()); + + environmentPostProcessor.configureSecurityContext(mockEnvironment); + + verify(mockEnvironment, times(2)).getPropertySources(); + + assertThat(propertySources.contains("boot.data.gemfire.cloudcache")).isTrue(); + + PropertySource propertySource = propertySources.get("boot.data.gemfire.cloudcache"); + + assertThat(propertySource).isNotNull(); + assertThat(propertySource.getName()).isEqualTo("boot.data.gemfire.cloudcache"); + assertThat(Boolean.parseBoolean(String.valueOf(propertySource + .getProperty("spring.data.gemfire.security.ssl.use-default-context")))).isTrue(); + } + @Test public void configureSecurityContextWhenNoCloudCacheServiceInstanceIsFoundLogsWarning() { diff --git a/spring-geode/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java b/spring-geode/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java index 2223bc1d..e3e8877f 100644 --- a/spring-geode/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java +++ b/spring-geode/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java @@ -76,6 +76,7 @@ public class VcapPropertySource extends PropertySource { static final int DEFAULT_LOCATOR_PORT = GemfireUtils.DEFAULT_LOCATOR_PORT; diff --git a/spring-geode/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java b/spring-geode/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java index a56da58f..5e659c06 100644 --- a/spring-geode/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java +++ b/spring-geode/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java @@ -24,8 +24,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.net.URL; @@ -59,6 +59,7 @@ import org.springframework.geode.core.env.support.User; * @see org.springframework.core.env.ConfigurableEnvironment * @see org.springframework.core.env.EnumerablePropertySource * @see org.springframework.core.env.Environment + * @see org.springframework.core.env.MutablePropertySources * @see org.springframework.core.env.PropertiesPropertySource * @see org.springframework.core.env.PropertySource * @see org.springframework.geode.core.env.VcapPropertySource @@ -114,7 +115,7 @@ public class VcapPropertySourceUnitTests { throw expected; } finally { - verifyZeroInteractions(mockEnvironment); + verifyNoInteractions(mockEnvironment); } } @@ -417,6 +418,107 @@ public class VcapPropertySourceUnitTests { verify(mockPropertySource, times(1)).getPropertyNames(); } + @Test + public void findFirstCloudCacheServiceReturnsOptionalOfCloudCacheService() { + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.services.test-pcc.name", "test-pcc"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache,database,gemfire,junk"); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + + Optional cloudCacheService = propertySource.findFirstCloudCacheService(); + + assertThat(cloudCacheService).isNotNull(); + assertThat(cloudCacheService.isPresent()).isTrue(); + assertThat(cloudCacheService.map(CloudCacheService::getName).orElse(null)).isEqualTo("test-pcc"); + assertThat(cloudCacheService.flatMap(CloudCacheService::getLocators).isPresent()).isFalse(); + assertThat(cloudCacheService.flatMap(CloudCacheService::getGfshUrl).isPresent()).isFalse(); + } + + @Test + public void findFirstCloudCacheServiceReturnsEmptyOptional() { + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.services.test-postresql.name", "TestPostreSQLDatabase"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.services.test-postresql.tags", "pivotal, database, postresql"); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + assertThat(propertySource.findFirstCloudCacheService().isPresent()).isFalse(); + } + + @Test + public void requireFirstCloudCacheServiceReturnsCloudCacheService() throws Exception { + + URL gfshUrl = new URL("https://skullbox:7070/v1/gemfire"); + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.services.test-pcc.name", "test-pcc"); + vcap.setProperty("vcap.services.test-pcc.plan", "huge"); + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.services.test-pcc.credentials.locators", "sandbox[1234],toolbox,xbox[6789]"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.services.test-pcc.credentials.urls.gfsh", gfshUrl.toExternalForm()); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache , database, gemfire "); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + + CloudCacheService cloudCacheService = propertySource.requireFirstCloudCacheService(); + + assertThat(cloudCacheService).isNotNull(); + assertThat(cloudCacheService.getName()).isEqualTo("test-pcc"); + assertThat(cloudCacheService.getGfshUrl().orElse(null)).isEqualTo(gfshUrl); + assertThat(cloudCacheService.isTlsEnabled()).isFalse(); + assertThat(cloudCacheService.getLocatorList()).containsExactly( + CloudCacheService.Locator.newLocator("sandbox", 1234), + CloudCacheService.Locator.newLocator("toolbox", 10334), + CloudCacheService.Locator.newLocator("xbox", 6789) + ); + } + + @Test(expected = IllegalStateException.class) + public void requireFirstCloudCacheServiceWhenNotFoundThrowsIllegalStateException() { + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.services.test-postresql.name", "TestPostreSQLDatabase"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.services.test-postresql.tags", "pivotal, database, postresql"); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + + try { + propertySource.requireFirstCloudCacheService(); + } + catch (IllegalStateException expected) { + + assertThat(expected).hasMessage("Unable to resolve a CloudCache Service Instance"); + assertThat(expected).hasNoCause(); + + throw expected; + } + } + @Test public void findFirstCloudCacheServiceNameReturnsOptionalOfServiceName() { @@ -515,106 +617,6 @@ public class VcapPropertySourceUnitTests { } } - @Test - public void findFirstCloudCacheServiceReturnsOptionalOfCloudCacheService() { - - Properties vcap = new Properties(); - - vcap.setProperty("vcap.application.name", "boot-example"); - vcap.setProperty("vcap.services.test-pcc.name", "test-pcc"); - vcap.setProperty("vcap.application.space_name", "outerspace"); - vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache,database,gemfire,junk"); - vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); - - VcapPropertySource propertySource = VcapPropertySource.from(vcap); - - assertThat(propertySource).isNotNull(); - - Optional cloudCacheService = propertySource.findFirstCloudCacheService(); - - assertThat(cloudCacheService).isNotNull(); - assertThat(cloudCacheService.isPresent()).isTrue(); - assertThat(cloudCacheService.map(CloudCacheService::getName).orElse(null)).isEqualTo("test-pcc"); - assertThat(cloudCacheService.flatMap(CloudCacheService::getLocators).isPresent()).isFalse(); - assertThat(cloudCacheService.flatMap(CloudCacheService::getGfshUrl).isPresent()).isFalse(); - } - - @Test - public void findFirstCloudCacheServiceReturnsEmptyOptional() { - - Properties vcap = new Properties(); - - vcap.setProperty("vcap.application.name", "boot-example"); - vcap.setProperty("vcap.services.test-postresql.name", "TestPostreSQLDatabase"); - vcap.setProperty("vcap.application.space_name", "outerspace"); - vcap.setProperty("vcap.services.test-postresql.tags", "pivotal, database, postresql"); - vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); - - VcapPropertySource propertySource = VcapPropertySource.from(vcap); - - assertThat(propertySource).isNotNull(); - assertThat(propertySource.findFirstCloudCacheService().isPresent()).isFalse(); - } - - @Test - public void requireFirstCloudCacheServiceReturnsCloudCacheService() throws Exception { - - URL gfshUrl = new URL("https://skullbox:7070/v1/gemfire"); - - Properties vcap = new Properties(); - - vcap.setProperty("vcap.services.test-pcc.name", "test-pcc"); - vcap.setProperty("vcap.services.test-pcc.plan", "huge"); - vcap.setProperty("vcap.application.name", "boot-example"); - vcap.setProperty("vcap.services.test-pcc.credentials.locators", "sandbox[1234],toolbox,xbox[6789]"); - vcap.setProperty("vcap.application.space_name", "outerspace"); - vcap.setProperty("vcap.services.test-pcc.credentials.urls.gfsh", gfshUrl.toExternalForm()); - vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); - vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache , database, gemfire "); - - VcapPropertySource propertySource = VcapPropertySource.from(vcap); - - assertThat(propertySource).isNotNull(); - - CloudCacheService cloudCacheService = propertySource.requireFirstCloudCacheService(); - - assertThat(cloudCacheService).isNotNull(); - assertThat(cloudCacheService.getName()).isEqualTo("test-pcc"); - assertThat(cloudCacheService.getGfshUrl().orElse(null)).isEqualTo(gfshUrl); - assertThat(cloudCacheService.getLocatorList()).containsExactly( - CloudCacheService.Locator.newLocator("sandbox", 1234), - CloudCacheService.Locator.newLocator("toolbox", 10334), - CloudCacheService.Locator.newLocator("xbox", 6789) - ); - } - - @Test(expected = IllegalStateException.class) - public void requireFirstCloudCacheServiceWhenNotFoundThrowsIllegalStateException() { - - Properties vcap = new Properties(); - - vcap.setProperty("vcap.application.name", "boot-example"); - vcap.setProperty("vcap.services.test-postresql.name", "TestPostreSQLDatabase"); - vcap.setProperty("vcap.application.space_name", "outerspace"); - vcap.setProperty("vcap.services.test-postresql.tags", "pivotal, database, postresql"); - vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); - - VcapPropertySource propertySource = VcapPropertySource.from(vcap); - - assertThat(propertySource).isNotNull(); - - try { - propertySource.requireFirstCloudCacheService(); - } - catch (IllegalStateException expected) { - - assertThat(expected).hasMessage("Unable to resolve a CloudCache Service Instance"); - assertThat(expected).hasNoCause(); - - throw expected; - } - } - @Test public void findUserByNameReturnsOptionalOfUser() { @@ -774,6 +776,52 @@ public class VcapPropertySourceUnitTests { assertThat(majorTom.getRole().map(User.Role::isClusterOperator).orElse(false)).isTrue(); } + @Test + public void cloudCacheServiceConfiguredWithTlsDisabled() { + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + vcap.setProperty("vcap.services.test-cloudcache.name", "TestCloudCache"); + vcap.setProperty("vcap.services.test-cloudcache.tags", "pivotal, cloudcache, database, gemfire"); + vcap.setProperty("vcap.services.test-cloudcache.credentials.tls-enabled", "false"); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + + CloudCacheService testCloudCacheService = propertySource.requireFirstCloudCacheService(); + + assertThat(testCloudCacheService).isNotNull(); + assertThat(testCloudCacheService.getName()).isEqualTo("test-cloudcache"); + assertThat(testCloudCacheService.isTlsEnabled()).isFalse(); + } + + @Test + public void cloudCacheServiceConfiguredWithTlsEnabled() { + + Properties vcap = new Properties(); + + vcap.setProperty("vcap.application.name", "boot-example"); + vcap.setProperty("vcap.application.space_name", "outerspace"); + vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net"); + vcap.setProperty("vcap.services.test-cloudcache.name", "TestCloudCache"); + vcap.setProperty("vcap.services.test-cloudcache.tags", "pivotal, cloudcache, database, gemfire"); + vcap.setProperty("vcap.services.test-cloudcache.credentials.tls-enabled", "true"); + + VcapPropertySource propertySource = VcapPropertySource.from(vcap); + + assertThat(propertySource).isNotNull(); + + CloudCacheService testCloudCacheService = propertySource.requireFirstCloudCacheService(); + + assertThat(testCloudCacheService).isNotNull(); + assertThat(testCloudCacheService.getName()).isEqualTo("test-cloudcache"); + assertThat(testCloudCacheService.isTlsEnabled()).isTrue(); + } + @Test @SuppressWarnings("unchecked") public void withMockVcapServicePredicateConfiguresVcapServicePredicateReturnsThis() { diff --git a/spring-geode/src/test/java/org/springframework/geode/core/env/support/CloudCacheServiceUnitTests.java b/spring-geode/src/test/java/org/springframework/geode/core/env/support/CloudCacheServiceUnitTests.java index 94398bba..8afe4257 100644 --- a/spring-geode/src/test/java/org/springframework/geode/core/env/support/CloudCacheServiceUnitTests.java +++ b/spring-geode/src/test/java/org/springframework/geode/core/env/support/CloudCacheServiceUnitTests.java @@ -13,7 +13,6 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ - package org.springframework.geode.core.env.support; import static org.assertj.core.api.Assertions.assertThat; @@ -34,7 +33,7 @@ import org.junit.Test; public class CloudCacheServiceUnitTests { @Test - public void withServiceNameLocatorsAndUrlReturnsNewCloudCacheService() throws Exception { + public void withServiceNameLocatorsAndGfshUrlReturnsNewCloudCacheService() throws Exception { URL gfshUrl = new URL("http://localhost:7070/v1/gemfire"); @@ -121,13 +120,15 @@ public class CloudCacheServiceUnitTests { public void parseLocatorsWithMultipleLocatorHostsPorts() { List locators = - CloudCacheService.Locator.parseLocators(" jukebox[12345], matchbox [6789] "); + CloudCacheService.Locator.parseLocators(" cardboardbox, jukebox[12345], matchbox , skullbox [6789] "); assertThat(locators).isNotNull(); - assertThat(locators).hasSize(2); + assertThat(locators).hasSize(4); assertThat(locators).containsExactly( + CloudCacheService.Locator.newLocator("cardboardbox", 10334), CloudCacheService.Locator.newLocator("jukebox", 12345), - CloudCacheService.Locator.newLocator("matchbox", 6789) + CloudCacheService.Locator.newLocator("matchbox", 10334), + CloudCacheService.Locator.newLocator("skullbox", 6789) ); } @@ -239,4 +240,34 @@ public class CloudCacheServiceUnitTests { assertThat(CloudCacheService.Locator.newLocator("skullbox", 1234).toString()) .isEqualTo("skullbox[1234]"); } + + @Test + public void tlsIsEnabledWhenSetToTrue() { + + CloudCacheService cloudCacheService = CloudCacheService.with("TestCloudCacheService"); + + assertThat(cloudCacheService).isNotNull(); + assertThat(cloudCacheService.withTls(true)).isEqualTo(cloudCacheService); + assertThat(cloudCacheService.isTlsEnabled()).isTrue(); + } + + @Test + public void tlsIsNotEnabledWhenSetToFalse() { + + CloudCacheService cloudCacheService = CloudCacheService.with("TestCloudCacheService"); + + assertThat(cloudCacheService).isNotNull(); + assertThat(cloudCacheService.withTls(false)).isEqualTo(cloudCacheService); + assertThat(cloudCacheService.isTlsEnabled()).isFalse(); + } + + @Test + public void tlsIsNotEnabledWhenSetToNull() { + + CloudCacheService cloudCacheService = CloudCacheService.with("TestCloudCacheService"); + + assertThat(cloudCacheService).isNotNull(); + assertThat(cloudCacheService.withTls(null)).isEqualTo(cloudCacheService); + assertThat(cloudCacheService.isTlsEnabled()).isFalse(); + } }