From b48bed486f58530f1c04a10df1cf4afef489564f Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Wed, 2 Jan 2013 13:21:58 -0500 Subject: [PATCH] INT-2868 Fix SSL Key Store Resource Handling Documentation indicates that the keystore and truststore arguments can be resource patterns (file:..., classpath:..., etc) but the code always used a ClasspathResource. Use a PathMatchingResourcePatternResolver to interpret the pattern correctly. Add tests. --- .../support/DefaultTcpSSLContextSupport.java | 24 +++++++++++-------- .../ip/config/ParserUnitTests-context.xml | 2 +- .../ip/config/ParserUnitTests.java | 16 +++++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/support/DefaultTcpSSLContextSupport.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/support/DefaultTcpSSLContextSupport.java index 8451eeb655..b7c54d4264 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/support/DefaultTcpSSLContextSupport.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/support/DefaultTcpSSLContextSupport.java @@ -15,7 +15,6 @@ */ package org.springframework.integration.ip.tcp.connection.support; -import java.io.FileInputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyStore; @@ -24,8 +23,8 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; -import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.util.Assert; /** @@ -38,9 +37,9 @@ import org.springframework.util.Assert; */ public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport { - private final String keyStore; + private final Resource keyStore; - private final String trustStore; + private final Resource trustStore; private final char[] keyStorePassword; @@ -51,15 +50,20 @@ public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport { /** * Prepares for the creation of an SSLContext using the supplied * key/trust stores and passwords. - * @param keyStore A {@link Resource} pointing to the keyStore. - * @param trustStore A {@link Resource} pointing to the trustStore. + * @param keyStore A {@link Resource} pattern pointing to the keyStore. + * @param trustStore A {@link Resource} pattern pointing to the trustStore. * @param keyStorePassword The passowrd for the keyStore. * @param trustStorePassword The password for the trustStore. */ public DefaultTcpSSLContextSupport(String keyStore, String trustStore, String keyStorePassword, String trustStorePassword) { - this.keyStore = keyStore; - this.trustStore = trustStore; + Assert.notNull(keyStore, "keyStore cannot be null"); + Assert.notNull(trustStore, "trustStore cannot be null"); + Assert.notNull(keyStorePassword, "keyStorePassword cannot be null"); + Assert.notNull(trustStorePassword, "trustStorePassword cannot be null"); + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + this.keyStore = resolver.getResource(keyStore); + this.trustStore = resolver.getResource(trustStore); this.keyStorePassword = keyStorePassword.toCharArray(); this.trustStorePassword = trustStorePassword.toCharArray(); } @@ -68,8 +72,8 @@ public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport { KeyStore ks = KeyStore.getInstance("JKS"); KeyStore ts = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(new ClassPathResource(keyStore).getFile()), keyStorePassword); - ts.load(new FileInputStream(new ClassPathResource(trustStore).getFile()), trustStorePassword); + ks.load(keyStore.getInputStream(), keyStorePassword); + ts.load(trustStore.getInputStream(), trustStorePassword); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, keyStorePassword); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml index cbfd3564aa..51e03db442 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml @@ -71,7 +71,7 @@ /> - + diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests.java index 27b5115e8d..702b6fd15d 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests.java @@ -33,6 +33,8 @@ import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.UrlResource; import org.springframework.core.serializer.Deserializer; import org.springframework.core.serializer.Serializer; import org.springframework.core.task.TaskExecutor; @@ -54,6 +56,8 @@ import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionF import org.springframework.integration.ip.tcp.connection.TcpNioClientConnectionFactory; import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory; import org.springframework.integration.ip.tcp.connection.support.DefaultTcpNetSSLSocketFactorySupport; +import org.springframework.integration.ip.tcp.connection.support.DefaultTcpSSLContextSupport; +import org.springframework.integration.ip.tcp.connection.support.TcpSSLContextSupport; import org.springframework.integration.ip.tcp.connection.support.TcpSocketFactorySupport; import org.springframework.integration.ip.tcp.connection.support.TcpSocketSupport; import org.springframework.integration.ip.udp.DatagramPacketMessageMapper; @@ -248,6 +252,9 @@ public class ParserUnitTests { @Autowired TcpSocketSupport socketSupport; + @Autowired + TcpSSLContextSupport contextSupport; + private static volatile int adviceCalled; @Test @@ -302,6 +309,15 @@ public class ParserUnitTests { Object socketSupport = TestUtils.getPropertyValue(cfS1, "tcpSocketFactorySupport"); assertTrue(socketSupport instanceof DefaultTcpNetSSLSocketFactorySupport); assertNotNull(TestUtils.getPropertyValue(socketSupport, "sslContext")); + + TcpSSLContextSupport contextSupport = TestUtils.getPropertyValue(cfS1, "tcpSocketFactorySupport.sslContextSupport", TcpSSLContextSupport.class); + assertSame(contextSupport, this.contextSupport); + assertTrue(TestUtils.getPropertyValue(contextSupport, "keyStore") instanceof ClassPathResource); + assertTrue(TestUtils.getPropertyValue(contextSupport, "trustStore") instanceof ClassPathResource); + + contextSupport = new DefaultTcpSSLContextSupport("http:foo", "file:bar", "", ""); + assertTrue(TestUtils.getPropertyValue(contextSupport, "keyStore") instanceof UrlResource); + assertTrue(TestUtils.getPropertyValue(contextSupport, "trustStore") instanceof UrlResource); } @Test