INT-3796: More SFTP Refinements
JIRA: https://jira.spring.io/browse/INT-3796 When a `UserInfo` is provided, use it for the password and passphrase. Disallow local properies when a `UserInfo` is provided. Simple polishing and fixing `TestSftpServer` for the `this.server.stop(true);` to avoid `port is already in use` for other tests which use default SSH port.
This commit is contained in:
committed by
Artem Bilan
parent
56bfe6b0ac
commit
e82bfdc9a6
@@ -126,9 +126,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
/**
|
||||
* The url of the host you want connect to. This is a mandatory property.
|
||||
*
|
||||
* @param host The host.
|
||||
*
|
||||
* @see JSch#getSession(String, String, int)
|
||||
*/
|
||||
public void setHost(String host) {
|
||||
@@ -139,9 +137,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* The port over which the SFTP connection shall be established. If not specified,
|
||||
* this value defaults to <code>22</code>. If specified, this properties must
|
||||
* be a positive number.
|
||||
*
|
||||
* @param port The port.
|
||||
*
|
||||
* @see JSch#getSession(String, String, int)
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
@@ -150,9 +146,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
/**
|
||||
* The remote user to use. This is a mandatory property.
|
||||
*
|
||||
* @param user The user.
|
||||
*
|
||||
* @see JSch#getSession(String, String, int)
|
||||
*/
|
||||
public void setUser(String user) {
|
||||
@@ -161,11 +155,11 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
/**
|
||||
* The password to authenticate against the remote host. If a password is
|
||||
* not provided, then the {@link DefaultSftpSessionFactory#privateKey} is
|
||||
* not provided, then a {@link DefaultSftpSessionFactory#setPrivateKey(Resource) privateKey} is
|
||||
* mandatory.
|
||||
*
|
||||
* Not allowed if {@link #setUserInfo(UserInfo) userInfo} is provided - the password is obtained
|
||||
* from that object.
|
||||
* @param password The password.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setPassword(String)
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
@@ -175,11 +169,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
/**
|
||||
* Specifies the filename that will be used for a host key repository.
|
||||
* The file has the same format as OpenSSH's known_hosts file.
|
||||
* Required if {@link #setAllowUnknownKeys(boolean) allowUnknownKeys} is
|
||||
* false (default).
|
||||
*
|
||||
* <p>
|
||||
* <b>Required if {@link #setAllowUnknownKeys(boolean) allowUnknownKeys} is
|
||||
* false (default).</b>
|
||||
* @param knownHosts The known hosts.
|
||||
*
|
||||
* @see JSch#setKnownHosts(String)
|
||||
*/
|
||||
public void setKnownHosts(String knownHosts) {
|
||||
@@ -189,14 +182,12 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
/**
|
||||
* Allows you to set a {@link Resource}, which represents the location of the
|
||||
* private key used for authenticating against the remote host. If the privateKey
|
||||
* is not provided, then the {@link DefaultSftpSessionFactory#setPassword(String)}
|
||||
* property is mandatory.
|
||||
*
|
||||
* is not provided, then the {@link DefaultSftpSessionFactory#setPassword(String) password}
|
||||
* property is mandatory (or {@link #setUserInfo(UserInfo) userInfo} that returns a
|
||||
* password.
|
||||
* @param privateKey The private key.
|
||||
*
|
||||
* @see JSch#addIdentity(String)
|
||||
* @see JSch#addIdentity(String, String)
|
||||
*
|
||||
*/
|
||||
public void setPrivateKey(Resource privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
@@ -204,9 +195,9 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
/**
|
||||
* The password for the private key. Optional.
|
||||
*
|
||||
* Not allowed if {@link #setUserInfo(UserInfo) userInfo} is provided - the passphrase is obtained
|
||||
* from that object.
|
||||
* @param privateKeyPassphrase The private key passphrase.
|
||||
*
|
||||
* @see JSch#addIdentity(String, String)
|
||||
*/
|
||||
public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
|
||||
@@ -216,9 +207,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
/**
|
||||
* Using {@link Properties}, you can set additional configuration settings on
|
||||
* the underlying JSch {@link com.jcraft.jsch.Session}.
|
||||
*
|
||||
* @param sessionConfig The session configuration properties.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setConfig(Properties)
|
||||
*/
|
||||
public void setSessionConfig(Properties sessionConfig) {
|
||||
@@ -228,12 +217,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
/**
|
||||
* Allows for specifying a JSch-based {@link Proxy}. If set, then the proxy
|
||||
* object is used to create the connection to the remote host.
|
||||
*
|
||||
* @param proxy The proxy.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setProxy(Proxy)
|
||||
*/
|
||||
public void setProxy(Proxy proxy){
|
||||
public void setProxy(Proxy proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
@@ -241,12 +228,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* Allows you to pass in a {@link SocketFactory}. The socket factory is used
|
||||
* to create a socket to the target host. When a {@link Proxy} is used, the
|
||||
* socket factory is passed to the proxy. By default plain TCP sockets are used.
|
||||
*
|
||||
* @param socketFactory The socket factory.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setSocketFactory(SocketFactory)
|
||||
*/
|
||||
public void setSocketFactory(SocketFactory socketFactory){
|
||||
public void setSocketFactory(SocketFactory socketFactory) {
|
||||
this.socketFactory = socketFactory;
|
||||
}
|
||||
|
||||
@@ -254,9 +239,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* The timeout property is used as the socket timeout parameter, as well as
|
||||
* the default connection timeout. Defaults to <code>0</code>, which means,
|
||||
* that no timeout will occur.
|
||||
*
|
||||
* @param timeout The timeout.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setTimeout(int)
|
||||
*/
|
||||
public void setTimeout(Integer timeout) {
|
||||
@@ -266,36 +249,30 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
/**
|
||||
* Allows you to set the client version property. It's default depends on the
|
||||
* underlying JSch version but it will look like <code>SSH-2.0-JSCH-0.1.45</code>
|
||||
*
|
||||
* @param clientVersion The client version.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setClientVersion(String)
|
||||
*/
|
||||
public void setClientVersion(String clientVersion){
|
||||
public void setClientVersion(String clientVersion) {
|
||||
this.clientVersion = clientVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host key alias, used when comparing the host key to the known
|
||||
* hosts list.
|
||||
*
|
||||
* @param hostKeyAlias The host key alias.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setHostKeyAlias(String)
|
||||
*/
|
||||
public void setHostKeyAlias(String hostKeyAlias){
|
||||
public void setHostKeyAlias(String hostKeyAlias) {
|
||||
this.hostKeyAlias = hostKeyAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout interval (milliseconds) before a server alive message is
|
||||
* sent, in case no message is received from the server.
|
||||
*
|
||||
* @param serverAliveInterval The server alive interval.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setServerAliveInterval(int)
|
||||
*/
|
||||
public void setServerAliveInterval(Integer serverAliveInterval){
|
||||
public void setServerAliveInterval(Integer serverAliveInterval) {
|
||||
this.serverAliveInterval = serverAliveInterval;
|
||||
}
|
||||
|
||||
@@ -303,12 +280,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* Specifies the number of server-alive messages, which will be sent without
|
||||
* any reply from the server before disconnecting. If not set, this property
|
||||
* defaults to <code>1</code>.
|
||||
*
|
||||
* @param serverAliveCountMax The server alive count max.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setServerAliveCountMax(int)
|
||||
*/
|
||||
public void setServerAliveCountMax(Integer serverAliveCountMax){
|
||||
public void setServerAliveCountMax(Integer serverAliveCountMax) {
|
||||
this.serverAliveCountMax = serverAliveCountMax;
|
||||
}
|
||||
|
||||
@@ -318,12 +293,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* underlying {@link com.jcraft.jsch.Session} using
|
||||
* {@link com.jcraft.jsch.Session#setDaemonThread(boolean)}. There, this
|
||||
* property will default to <code>false</code>, if not explicitly set.
|
||||
*
|
||||
* @param enableDaemonThread true to enable a daemon thread.
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#setDaemonThread(boolean)
|
||||
*/
|
||||
public void setEnableDaemonThread(Boolean enableDaemonThread){
|
||||
public void setEnableDaemonThread(Boolean enableDaemonThread) {
|
||||
this.enableDaemonThread = enableDaemonThread;
|
||||
}
|
||||
|
||||
@@ -342,7 +315,10 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* <p>
|
||||
* If {@link #setPassword(String) setPassword} is invoked with a non-null password, it will
|
||||
* override any password in the supplied {@link UserInfo}.
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE: When this is provided, the {@link #setPassword(String) password} and
|
||||
* {@link #setPrivateKeyPassphrase(String) passphrase} are not allowed because those values
|
||||
* will be obtained from the {@link UserInfo}.</b>
|
||||
* @param userInfo the UserInfo.
|
||||
* @see com.jcraft.jsch.Session#setUserInfo(com.jcraft.jsch.UserInfo)
|
||||
* @since 4.1.7
|
||||
@@ -356,7 +332,6 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
* connecting to an unknown host or when a host's key has changed (see
|
||||
* {@link #setKnownHosts(String) knownHosts}). Default false (since 4.2).
|
||||
* Set to true if a knownHosts file is not provided.
|
||||
*
|
||||
* @param allowUnknownKeys true to allow connecting to unknown hosts.
|
||||
* @since 4.1.7
|
||||
*/
|
||||
@@ -369,7 +344,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
Assert.hasText(this.host, "host must not be empty");
|
||||
Assert.hasText(this.user, "user must not be empty");
|
||||
Assert.isTrue(this.port >= 0, "port must be a positive number");
|
||||
Assert.isTrue(StringUtils.hasText(this.password) || this.privateKey != null,
|
||||
Assert.isTrue(StringUtils.hasText(this.userInfoWrapper.getPassword()) || this.privateKey != null,
|
||||
"either a password or a private key is required");
|
||||
try {
|
||||
JSchSessionWrapper jschSession;
|
||||
@@ -421,49 +396,53 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
// private key
|
||||
if (this.privateKey != null) {
|
||||
byte[] keyByteArray = StreamUtils.copyToByteArray(this.privateKey.getInputStream());
|
||||
if (StringUtils.hasText(this.privateKeyPassphrase)) {
|
||||
this.jsch.addIdentity(this.user, keyByteArray, null, this.privateKeyPassphrase.getBytes());
|
||||
String passphrase = this.userInfoWrapper.getPassphrase();
|
||||
if (StringUtils.hasText(passphrase)) {
|
||||
this.jsch.addIdentity(this.user, keyByteArray, null, passphrase.getBytes());
|
||||
}
|
||||
else {
|
||||
this.jsch.addIdentity(this.user, keyByteArray, null, null);
|
||||
}
|
||||
}
|
||||
com.jcraft.jsch.Session jschSession = this.jsch.getSession(this.user, this.host, this.port);
|
||||
if (this.sessionConfig != null){
|
||||
if (this.sessionConfig != null) {
|
||||
jschSession.setConfig(this.sessionConfig);
|
||||
}
|
||||
if (StringUtils.hasText(this.password)) {
|
||||
jschSession.setPassword(this.password);
|
||||
String password = this.userInfoWrapper.getPassword();
|
||||
if (StringUtils.hasText(password)) {
|
||||
jschSession.setPassword(password);
|
||||
}
|
||||
jschSession.setUserInfo(this.userInfoWrapper);
|
||||
|
||||
try {
|
||||
if (proxy != null){
|
||||
if (proxy != null) {
|
||||
jschSession.setProxy(proxy);
|
||||
}
|
||||
if (socketFactory != null){
|
||||
if (socketFactory != null) {
|
||||
jschSession.setSocketFactory(socketFactory);
|
||||
}
|
||||
if (timeout != null){
|
||||
if (timeout != null) {
|
||||
jschSession.setTimeout(timeout);
|
||||
}
|
||||
if (StringUtils.hasText(clientVersion)){
|
||||
if (StringUtils.hasText(clientVersion)) {
|
||||
jschSession.setClientVersion(clientVersion);
|
||||
}
|
||||
if (StringUtils.hasText(hostKeyAlias)){
|
||||
if (StringUtils.hasText(hostKeyAlias)) {
|
||||
jschSession.setHostKeyAlias(hostKeyAlias);
|
||||
}
|
||||
if (serverAliveInterval != null){
|
||||
if (serverAliveInterval != null) {
|
||||
jschSession.setServerAliveInterval(serverAliveInterval);
|
||||
}
|
||||
if (serverAliveCountMax != null){
|
||||
if (serverAliveCountMax != null) {
|
||||
jschSession.setServerAliveCountMax(serverAliveCountMax);
|
||||
}
|
||||
if (enableDaemonThread != null){
|
||||
if (enableDaemonThread != null) {
|
||||
jschSession.setDaemonThread(enableDaemonThread);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BeanCreationException("Attempt to set additional properties of the com.jcraft.jsch.Session resulted in error: " + e.getMessage(), e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new BeanCreationException("Attempt to set additional properties of " +
|
||||
"the com.jcraft.jsch.Session resulted in error: " + e.getMessage(), e);
|
||||
}
|
||||
return jschSession;
|
||||
}
|
||||
@@ -498,7 +477,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
/**
|
||||
* Convenience to retrieve enclosing factory's UserInfo.
|
||||
* @return
|
||||
* @return the {@link #userInfo} or null if not present.
|
||||
*/
|
||||
private UserInfo getDelegate() {
|
||||
return DefaultSftpSessionFactory.this.userInfo;
|
||||
@@ -507,27 +486,25 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
@Override
|
||||
public String getPassphrase() {
|
||||
if (hasDelegate()) {
|
||||
Assert.state(!StringUtils.hasText(DefaultSftpSessionFactory.this.privateKeyPassphrase),
|
||||
"When a 'UserInfo' is provided, 'privateKeyPassphrase' is not allowed");
|
||||
return getDelegate().getPassphrase();
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No UserInfo provided for passphrase, returning: null");
|
||||
}
|
||||
return null;
|
||||
return DefaultSftpSessionFactory.this.privateKeyPassphrase;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
if (hasDelegate()) {
|
||||
if (DefaultSftpSessionFactory.this.password != null) {
|
||||
logger.debug("Password is obtained from the factory, not the supplied UserInfo");
|
||||
}
|
||||
else {
|
||||
return getDelegate().getPassword();
|
||||
}
|
||||
Assert.state(!StringUtils.hasText(DefaultSftpSessionFactory.this.password),
|
||||
"When a 'UserInfo' is provided, 'password' is not allowed");
|
||||
return getDelegate().getPassword();
|
||||
}
|
||||
else {
|
||||
return DefaultSftpSessionFactory.this.password;
|
||||
}
|
||||
return DefaultSftpSessionFactory.this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -558,6 +535,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
@Override
|
||||
public boolean promptYesNo(String message) {
|
||||
logger.info(message);
|
||||
if (hasDelegate()) {
|
||||
return getDelegate().promptYesNo(message);
|
||||
}
|
||||
@@ -582,18 +560,18 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
|
||||
|
||||
@Override
|
||||
public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt,
|
||||
boolean[] echo) {
|
||||
if (hasDelegate()) {
|
||||
if (getDelegate() instanceof UIKeyboardInteractive) {
|
||||
return ((UIKeyboardInteractive) getDelegate()).promptKeyboardInteractive(destination, name,
|
||||
instruction, prompt, echo);
|
||||
boolean[] echo) {
|
||||
if (hasDelegate() && getDelegate() instanceof UIKeyboardInteractive) {
|
||||
return ((UIKeyboardInteractive) getDelegate()).promptKeyboardInteractive(destination, name,
|
||||
instruction, prompt, echo);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No UIKeyboardInteractive provided - " + destination + ":" + name + ":" + instruction
|
||||
+ ":" + Arrays.asList(prompt) + ":" + Arrays.asList(echo));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No UserInfo provided - " + destination + ":" + name + ":" + instruction + ":"
|
||||
+ Arrays.asList(prompt) + ":" + Arrays.asList(echo));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ public class TestSftpServer implements InitializingBean, DisposableBean {
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
this.server.stop();
|
||||
this.server.stop(true);
|
||||
this.sftpFolder.delete();
|
||||
this.localFolder.delete();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ import com.jcraft.jsch.ChannelSftp.LsEntry;
|
||||
*/
|
||||
public class SftpServerTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testUcPw() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
@@ -95,11 +94,20 @@ public class SftpServerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testPubPrivKey() throws Exception {
|
||||
testKeyExchange("id_rsa.pub", "id_rsa", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPubPrivKeyPassphrase() throws Exception {
|
||||
testKeyExchange("id_rsa_pp.pub", "id_rsa_pp", "secret");
|
||||
}
|
||||
|
||||
private void testKeyExchange(String pubKey, String privKey, String passphrase)
|
||||
throws Exception, IOException, InterruptedException {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
SshServer server = SshServer.setUpDefaultServer();
|
||||
final PublicKey allowedKey = decodePublicKey();
|
||||
final PublicKey allowedKey = decodePublicKey(pubKey);
|
||||
try {
|
||||
server.setPublickeyAuthenticator(new PublickeyAuthenticator() {
|
||||
|
||||
@@ -122,8 +130,9 @@ public class SftpServerTests {
|
||||
f.setPort(port);
|
||||
f.setUser("user");
|
||||
f.setAllowUnknownKeys(true);
|
||||
InputStream stream = new ClassPathResource("id_rsa").getInputStream();
|
||||
InputStream stream = new ClassPathResource(privKey).getInputStream();
|
||||
f.setPrivateKey(new ByteArrayResource(StreamUtils.copyToByteArray(stream)));
|
||||
f.setPrivateKeyPassphrase(passphrase);
|
||||
Session<LsEntry> session = f.getSession();
|
||||
doTest(server, session);
|
||||
}
|
||||
@@ -132,8 +141,8 @@ public class SftpServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
private PublicKey decodePublicKey() throws Exception {
|
||||
InputStream stream = new ClassPathResource("id_rsa.pub").getInputStream();
|
||||
private PublicKey decodePublicKey(String key) throws Exception {
|
||||
InputStream stream = new ClassPathResource(key).getInputStream();
|
||||
byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream));
|
||||
ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
|
||||
int len = bb.getInt();
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.integration.sftp.session;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -44,6 +45,7 @@ import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.test.util.SocketUtils;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.UserInfo;
|
||||
@@ -117,6 +119,41 @@ public class SftpSessionFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordPassPhraseViaUserInfo() throws Exception {
|
||||
DefaultSftpSessionFactory f = new DefaultSftpSessionFactory();
|
||||
f.setHost("localhost");
|
||||
f.setPort(9999);
|
||||
f.setUser("user");
|
||||
f.setAllowUnknownKeys(true);
|
||||
UserInfo ui = mock(UserInfo.class);
|
||||
when(ui.getPassword()).thenReturn("pass");
|
||||
when(ui.getPassphrase()).thenReturn("pp").thenReturn(null);
|
||||
f.setUserInfo(ui);
|
||||
UserInfo userInfo = TestUtils.getPropertyValue(f, "userInfoWrapper", UserInfo.class);
|
||||
assertEquals("pass", userInfo.getPassword());
|
||||
f.setPassword("foo");
|
||||
try {
|
||||
userInfo.getPassword();
|
||||
fail("expected Exception");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage(), startsWith("When a 'UserInfo' is provided, 'password' is not allowed"));
|
||||
}
|
||||
assertEquals("pp", userInfo.getPassphrase());
|
||||
f.setPrivateKeyPassphrase("bar");
|
||||
try {
|
||||
userInfo.getPassphrase();
|
||||
fail("expected Exception");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage(), startsWith("When a 'UserInfo' is provided, 'privateKeyPassphrase' is not allowed"));
|
||||
}
|
||||
f.setUserInfo(null);
|
||||
assertEquals("foo", userInfo.getPassword());
|
||||
assertEquals("bar", userInfo.getPassphrase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultUserInfoFalse() throws Exception {
|
||||
SshServer server = SshServer.setUpDefaultServer();
|
||||
@@ -143,7 +180,7 @@ public class SftpSessionFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomtUserInfoFalse() throws Exception {
|
||||
public void testCustomUserInfoFalse() throws Exception {
|
||||
SshServer server = SshServer.setUpDefaultServer();
|
||||
try {
|
||||
DefaultSftpSessionFactory f = createServerAndClient(server);
|
||||
@@ -171,7 +208,7 @@ public class SftpSessionFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomtUserInfoTrue() throws Exception {
|
||||
public void testCustomUserInfoTrue() throws Exception {
|
||||
SshServer server = SshServer.setUpDefaultServer();
|
||||
try {
|
||||
DefaultSftpSessionFactory f = createServerAndClient(server);
|
||||
|
||||
30
spring-integration-sftp/src/test/resources/id_rsa_pp
Normal file
30
spring-integration-sftp/src/test/resources/id_rsa_pp
Normal file
@@ -0,0 +1,30 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,26D1755B05980BA01B1E8D3B65EF98D3
|
||||
|
||||
J5fMQDf0HrwcnfYujq+q05GEOSEMVWMU0vr0hBtz2WvUeaFBBVAvUWbJo7PHTdDV
|
||||
vEdSv+k8FazOkIZpeOW26pKNaLSuFfN+lgtAW4p4yqGQhbL8byh+Ka5uGaPH1xQj
|
||||
o4exMFqbwFaHG10LJoPp5NnK+T64w8McJEihBPxv/qwtsz0YhhDVl/1eSwKsGa5y
|
||||
Usfdv0QbjNDtpV7+sy7OunpaaKjb8iQ/PbFDsX0TSiy6jJflPwCYVUoh3jCEJze3
|
||||
OUKwoQu7AiHmUrsnLtDuL49Q5hV+f9+IPJlzSqU5Fu8PlfCowH+e8WWLVQkh7Hht
|
||||
iwOQs5UIWH+Nzbguu3Gbph5lqMtgkQwK6/PSFLQXuJmf9l6eo7E+Wh5mFWwoIENT
|
||||
mKUlgVU0ymajPHcA7uOVXl5XX+Mt0DiMdGiB4N6RJ1OjWgqlRSJbVmGPrnZWmjdW
|
||||
VltNux6JrO1bOgwtApCouDZhnP7/JDhM2PCa/F2+XCc6s8Hnmmt+gBw6IM4fb+YH
|
||||
2gf1jx5Onp1yuBGe6tvbrfPAdXYU1R3kd2+Yf5mdsu2+xiC4wBKSfjleoHN4xJ/b
|
||||
wopjQvGV5dj/VjdUt99lMHGWPr+p4NmdEBoriCgjYuRjRDvCiTV2qKZe2MU+0CVE
|
||||
/jCA8iMRQnx3LMjnmJXP/96j2fyXHMowClTF43Cvdc5jh622WITOOFAIq9RfIXdS
|
||||
47G6FAN54V+Qt0pXEgIOmvG+B2C24A041fo3jUPZxFRSYYuv9vG6QJby3kCsaqqt
|
||||
ngYs2JSKx9CfOfGfyPbNt2/CO/bBsXgYzLR7REx5My1Mp9YsDmeIgbcd2V5hw/Me
|
||||
rlSXrG4Eqs9gRDrBUvsydUOJFC1PlnIXH3VSBc6X9o4n2H6XECOsJQSeXLCaeMav
|
||||
deKb0r1HvdbAYrdqw6mRM8Ok3fpSoD3mUsZQ8fp3luO3tHL1lddxHb7EsKzt/ubh
|
||||
B9lEzDTcILlINlCl41X0OZKr/c+Ec8EdaSvITYJj0fvaZmDF7Wcs/dDWNft2XUaD
|
||||
VcptOKbQVE1ufbrc2s1BdKOriAC6dSVKVDrAUQD/MlhT3p/YwbjSY2MqwRKztWRv
|
||||
sA1Kqjg1IdUQzQizRKuHa322qnduLjHy0rb0ElrMpFe3B+OcIPs1E7Gvo4BVQ5jU
|
||||
5GqHm83iaFIQaXmEsrVtCOBygVf00+WNRV3WFTOP9UEWFgtxsaHAU8UZhsDbKcZ5
|
||||
l/w6kQdNElQuJA+1n1OxRZ5wIpfrRIMaxBQg2plUTVb9Tgz1qTZxHIEYPAAePfvX
|
||||
tDn9SBiktj/8dhy1T0ko89yXCekpGxkU9rbmAd4Lrp6Wbc6+bKt4KzAqw319qq9U
|
||||
Pslq7EKNM0Zq5pfwn1MRjzvmyHxz2sYHeij0CmuZY7xuOa4NzXt1vr6nSlIpX77W
|
||||
ng/Rnd7qpyG2IWYihi6ztFHyj9h3FEcBHMk4JINLcdYOxXICz3KsRMfntrwQ4E6O
|
||||
NFJ3fPpVNkk4GZcxy6idNkUBz1s8ixVWC8yi36byxE+TTRtcvqXQnJVgs63vMUlC
|
||||
HVwaGau4YeUp4Nj2ZO44Srd/kQRy8yuCOPDdlJEiO6eDD4+XKedJQg1LuGeoXMVn
|
||||
-----END RSA PRIVATE KEY-----
|
||||
1
spring-integration-sftp/src/test/resources/id_rsa_pp.pub
Normal file
1
spring-integration-sftp/src/test/resources/id_rsa_pp.pub
Normal file
@@ -0,0 +1 @@
|
||||
AAAAB3NzaC1yc2EAAAADAQABAAABAQC6MIzgyVi8G1+HRhFHPWRH+3w/8/uxtiuIfb4puVPjHI53Lvf5odzfhv0T6Z2/jSXmI3I6dpjbsgiptdCTX4kqUFLXxkuJR4LHatNtgO1w32aVIdAvfj7KtrL3SmP2XWqQGVcUWHEn2H1RHFHKdC6ArYFb1X8p5N/BHSQjuttaeVi9FsDxvC5euIbtDEEJmmvjjfWlI1m/6qCqMYxDWA9i9APU/rB0QwFNUQ6HuZ2QzEaU/hQMGmqgW5o1I/W8JR0bqis8wZQDLv1fwCkXpWG5BAuiJH+FJMxRAkfEMBpVwO7Sl0ufePVuSM2BMAAe+4a75sVp8ahbOId6y0GUTeJl
|
||||
@@ -108,8 +108,7 @@ The file has the same format as OpenSSH's _known_hosts_ file and is required and
|
||||
|
||||
The password to authenticate against the remote host.
|
||||
If a _password_ is not provided, then the _privateKey_ property is mandatory.
|
||||
Overrides the password in a custom `UserInfo`.
|
||||
To use that password, leave this as the default `null`.
|
||||
Not allowed if `userInfo` is set; the password is obtained from that object.
|
||||
|
||||
*port*
|
||||
|
||||
@@ -125,6 +124,7 @@ If the _privateKey_ is not provided, then the _password_ property is mandatory.
|
||||
*privateKeyPassphrase*
|
||||
|
||||
The password for the private key.
|
||||
Not allowed if `userInfo` is set; the passphrase is obtained from that object.
|
||||
Optional.
|
||||
|
||||
*proxy*
|
||||
@@ -173,8 +173,10 @@ If false, a pre-populated knownHosts file is required.
|
||||
*userInfo*
|
||||
|
||||
Set a custom `UserInfo` used during authentication.
|
||||
In particular, `promptYesNo()` is invoked when an unknown (or changed) host key is received.
|
||||
In particular, be aware that `promptYesNo()` is invoked when an unknown (or changed) host key is received.
|
||||
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-dsf]]
|
||||
|
||||
@@ -309,9 +309,12 @@ See <<ftp-dsf>> and <<sftp-dsf>> for more information.
|
||||
|
||||
===== DefaultSftpSessionFactory
|
||||
|
||||
Previously, the `DefaultSftpSessionFactory` allowed connections to unknown hosts.
|
||||
Previously, the `DefaultSftpSessionFactory` unconditionally allowed connections to unknown hosts.
|
||||
This is now configurable (default false).
|
||||
|
||||
The factory now requires a configured `knownHosts` file unless the `allowUnknownKeys` property is `true` (default
|
||||
false).
|
||||
|
||||
See <<sftp-unk-hosts>> for more information.
|
||||
|
||||
==== Websocket Changes
|
||||
|
||||
Reference in New Issue
Block a user