diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/JschProxyFactoryBean.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/JschProxyFactoryBean.java new file mode 100644 index 0000000000..ec4a1c2b9c --- /dev/null +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/JschProxyFactoryBean.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.sftp.session; + +import org.springframework.beans.factory.config.AbstractFactoryBean; + +import com.jcraft.jsch.Proxy; +import com.jcraft.jsch.ProxyHTTP; +import com.jcraft.jsch.ProxySOCKS4; +import com.jcraft.jsch.ProxySOCKS5; + +/** + * Spring-friendly factory bean to create Jsch {@link Proxy} objects. + * + * @author Gary Russell + * @since 4.3 + * + */ +public class JschProxyFactoryBean extends AbstractFactoryBean { + + public enum Type { + HTTP, SOCKS4, SOCKS5 + } + + private final Type type; + + private final String host; + + private final int port; + + private final String user; + + private final String password; + + public JschProxyFactoryBean(Type type, String host, int port, String user, String password) { + this.type = type; + this.host = host; + this.port = port; + this.user = user; + this.password = password; + } + + @Override + public Class getObjectType() { + switch (this.type) { + case SOCKS5: + return ProxySOCKS5.class; + case SOCKS4: + return ProxySOCKS4.class; + case HTTP: + return ProxyHTTP.class; + default: + throw new UnsupportedOperationException("Invalid type:" + this.type); + } + } + + @Override + protected Proxy createInstance() throws Exception { + switch (this.type) { + case SOCKS5: + ProxySOCKS5 socks5proxy = new ProxySOCKS5(this.host, this.port); + socks5proxy.setUserPasswd(this.user, this.password); + return socks5proxy; + case SOCKS4: + ProxySOCKS4 socks4proxy = new ProxySOCKS4(this.host, this.port); + socks4proxy.setUserPasswd(this.user, this.password); + return socks4proxy; + case HTTP: + ProxyHTTP httpProxy = new ProxyHTTP(this.host, this.port); + httpProxy.setUserPasswd(this.user, this.password); + return httpProxy; + default: + throw new UnsupportedOperationException("Invalid type:" + this.type); + } + } + +} diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/ProxyTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/ProxyTests.java new file mode 100644 index 0000000000..7711845cb2 --- /dev/null +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/ProxyTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.sftp.session; + +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Ignore; +import org.junit.Test; + +import org.springframework.integration.test.util.TestUtils; + +import com.jcraft.jsch.Proxy; +import com.jcraft.jsch.ProxyHTTP; +import com.jcraft.jsch.ProxySOCKS4; +import com.jcraft.jsch.ProxySOCKS5; + +/** + * @author Gary Russell + * @since 4.3 + * + */ +public class ProxyTests { + + @Test + @Ignore + /* + * Needs host and account + */ + public void testSimpleConnect() { + DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory(); + sf.setHost("10.0.0.3"); + sf.setPort(22); + sf.setUser("ftptest"); + sf.setPassword("ftptest"); + sf.setAllowUnknownKeys(true); + sf.getSession().close(); + } + + @Test + @Ignore + /* + * Needs host and account and... + * $ ssh -D 1080 -f -N gpr@10.0.0.3 + */ + public void testProxyConnect() throws Exception { + DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory(); + JschProxyFactoryBean proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS5, "localhost", + 1080, "ftptest", "ftptest"); + proxyFactoryBean.afterPropertiesSet(); + sf.setHost("10.0.0.3"); + sf.setPort(22); + sf.setUser("ftptest"); + sf.setPassword("ftptest"); + sf.setProxy(proxyFactoryBean.getObject()); + sf.setAllowUnknownKeys(true); + sf.getSession().close(); + } + + @Test + public void testFactoryBean() throws Exception { + JschProxyFactoryBean proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS5, "localhost", + 1080, "ftptest", "pass"); + proxyFactoryBean.afterPropertiesSet(); + Proxy proxy = proxyFactoryBean.getObject(); + assertProxy(proxy, ProxySOCKS5.class); + + proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS4, "localhost", + 1080, "ftptest", "pass"); + proxyFactoryBean.afterPropertiesSet(); + proxy = proxyFactoryBean.getObject(); + assertProxy(proxy, ProxySOCKS4.class); + + proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.HTTP, "localhost", + 1080, "ftptest", "pass"); + proxyFactoryBean.afterPropertiesSet(); + proxy = proxyFactoryBean.getObject(); + assertProxy(proxy, ProxyHTTP.class); + } + + private void assertProxy(Proxy proxy, Class clazz) { + assertThat(proxy, instanceOf(clazz)); + assertEquals("ftptest", TestUtils.getPropertyValue(proxy, "user")); + assertEquals("pass", TestUtils.getPropertyValue(proxy, "passwd")); + } + +} diff --git a/src/reference/asciidoc/sftp.adoc b/src/reference/asciidoc/sftp.adoc index b62799df1d..5207079eb9 100644 --- a/src/reference/asciidoc/sftp.adoc +++ b/src/reference/asciidoc/sftp.adoc @@ -129,7 +129,8 @@ Optional. *proxy* Allows for specifying a JSch-based http://epaul.github.com/jsch-documentation/javadoc/com/jcraft/jsch/Proxy.html[Proxy]. -If set, then the proxy object is used to create the connection to the remote host. +If set, then the proxy object is used to create the connection to the remote host via the proxy. +See <> for a convenient way to configure the proxy. *serverAliveCountMax* @@ -177,6 +178,33 @@ Also see `allowUnknownHosts`. When a `UserInfo` is provided, the `password` and private key `passphrase` is obtained from it, and discrete `password` and `privateKeyPassprase` properties cannot be set. +[[sftp-proxy-factory-bean]] +=== Proxy Factory Bean + +`Jsch` provides a mechanism to connect to the server via an HTTP or SOCKS proxy. +To use this feature, configure the `Proxy` and provide a reference to the `DefaultSftpSessionFactory` as discussed +above. +Three implementations are provided by `Jsch`, `HTTP`, `SOCKS4` and `SOCKS5`. +_Spring Integration 4.3_ provides a `FactoryBean` making configuration of these proxies easier, allowing property +injection: + +[source, xml] +---- + + + + + + + + + + ... + + ... + +---- [[sftp-dsf]] === Delegating Session Factory diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 092d00331f..4c4c03bc63 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -92,3 +92,8 @@ Previously, with requests that had a body (such as `POST`) that had no `content- With this release, the content type of such requests is considered to be `application/octet-stream` as recommended by RFC 2616. See <> for more information. + +==== SFTP Changes + +A new factory bean is provided to simplify the configuration of Jsch proxies for SFTP. +See <> for more information.