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.
This commit is contained in:
Gary Russell
2013-01-02 13:21:58 -05:00
committed by Gunnar Hillert
parent df6a8dee04
commit b48bed486f
3 changed files with 31 additions and 11 deletions

View File

@@ -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);

View File

@@ -71,7 +71,7 @@
/>
<bean id="sslContextSupport" class="org.springframework.integration.ip.tcp.connection.support.DefaultTcpSSLContextSupport">
<constructor-arg value="test.ks"/>
<constructor-arg value="classpath:test.ks"/>
<constructor-arg value="test.truststore.ks"/>
<constructor-arg value="secret"/>
<constructor-arg value="secret"/>

View File

@@ -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