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.
This commit is contained in:
John Blum
2019-10-17 15:50:26 -07:00
parent afbbfe9991
commit 25960adc4d
6 changed files with 276 additions and 109 deletions

View File

@@ -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> 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> 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() {

View File

@@ -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<CloudCacheService.Locator> 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();
}
}