Skip to content

Commit

Permalink
GH-3211: Add DefSftpSF.setKnownHosts(Resource) (#3212)
Browse files Browse the repository at this point in the history
* GH-3211: Add DefSftpSF.setKnownHosts(Resource)

Fixes #3211

* Add `DefaultSftpSessionFactory.setKnownHosts(Resource)` to
allow to configure externally any resource for file with known_hosts content
* Deprecate an existing method in favor of new one
* The new method makes it aligned with the `setPrivateKey(Resource)`
* Fix tests do not use a deprecated method any more

**Cherry-pick to 5.2.x**

* * Rename to `setKnownHostsResource()` to avoid XML parser confusion
* Change `sftp.adoc` to reflect a new property
  • Loading branch information
artembilan committed Mar 10, 2020
1 parent 36f96ec commit 6b82681
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
Expand All @@ -17,6 +17,7 @@
package org.springframework.integration.sftp.session;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Arrays;
import java.util.Properties;
Expand All @@ -27,6 +28,7 @@
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.file.remote.session.SharedSessionCapable;
Expand Down Expand Up @@ -81,7 +83,7 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share

private String password;

private String knownHosts;
private Resource knownHosts;

private Resource privateKey;

Expand Down Expand Up @@ -191,8 +193,21 @@ public void setPassword(String password) {
* false (default).</b>
* @param knownHosts The known hosts.
* @see JSch#setKnownHosts(String)
* @deprecated since 5.2.5 in favor of {@link #setKnownHostsResource(Resource)}
*/
@Deprecated
public void setKnownHosts(String knownHosts) {
setKnownHostsResource(new FileSystemResource(knownHosts));
}

/**
* Specifies the filename that will be used for a host key repository.
* The file has the same format as OpenSSH's known_hosts file.
* @param knownHosts the resource for known hosts.
* @see JSch#setKnownHosts(InputStream)
* @since 5.2.5
*/
public void setKnownHostsResource(Resource knownHosts) {
this.knownHosts = knownHosts;
}

Expand Down Expand Up @@ -323,7 +338,7 @@ public void setEnableDaemonThread(Boolean enableDaemonThread) {
* implementation must respond to Jsch calls in a suitable way.
* <p>
* Jsch calls {@link UserInfo#promptYesNo(String)} when connecting to an unknown host,
* or when a known host's key has changed (see {@link #setKnownHosts(String)
* or when a known host's key has changed (see {@link #setKnownHostsResource(Resource)}
* knownHosts}). Generally, it should return false as returning true will accept all
* new keys or key changes.
* <p>
Expand All @@ -347,7 +362,7 @@ public void setUserInfo(UserInfo userInfo) {
/**
* When no {@link UserInfo} has been provided, set to true to unconditionally allow
* connecting to an unknown host or when a host's key has changed (see
* {@link #setKnownHosts(String) knownHosts}). Default false (since 4.2).
* {@link #setKnownHostsResource(Resource) 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
Expand Down Expand Up @@ -380,8 +395,7 @@ public SftpSession getSession() {
freshJschSession = true;
}
sftpSession = new SftpSession(jschSession);
JavaUtils.INSTANCE
.acceptIfNotNull(this.channelConnectTimeout, sftpSession::setChannelConnectTimeout);
JavaUtils.INSTANCE.acceptIfNotNull(this.channelConnectTimeout, sftpSession::setChannelConnectTimeout);
sftpSession.connect();
if (this.isSharedSession && freshJschSession) {
this.sharedJschSession = jschSession;
Expand All @@ -408,8 +422,8 @@ private com.jcraft.jsch.Session initJschSession() throws JSchException, IOExcept
if (this.port <= 0) {
this.port = 22;
}
if (StringUtils.hasText(this.knownHosts)) {
this.jsch.setKnownHosts(this.knownHosts);
if (this.knownHosts != null) {
this.jsch.setKnownHosts(this.knownHosts.getInputStream());
}

// private key
Expand Down Expand Up @@ -467,6 +481,7 @@ public void resetSharedSession() {
* sensible defaults if null. As the password is configured in this Factory, the
* wrapper will return the factory's configured password and only delegate to the
* UserInfo if null.
*
* @since 4.1.7
*/
private class UserInfoWrapper implements UserInfo, UIKeyboardInteractive {
Expand Down Expand Up @@ -548,7 +563,7 @@ public boolean promptYesNo(String message) {
}
else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("No UserInfo provided - " + message + ", returning:"
LOGGER.debug("No UserInfo provided - " + message + ", returning: "
+ DefaultSftpSessionFactory.this.allowUnknownKeys);
}
return DefaultSftpSessionFactory.this.allowUnknownKeys;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<beans:bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<beans:property name="host" value="loclahost"/>
<beans:property name="knownHosts" value="local, foo.com, bar.foo"/>
<beans:property name="knownHostsResource" value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<beans:property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftp_rsa"/>
<beans:property name="privateKeyPassphrase" value="ghj"/>
<beans:property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,17 @@
xmlns="http://www.springframework.org/schema/integration"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tool https://www.springframework.org/schema/tool/spring-tool.xsd
http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/integration/sftp https://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">

<channel id="requestChannel"/>

<beans:bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<beans:property name="host" value="loclahost"/>
<beans:property name="knownHosts" value="local, foo.com, bar.foo"/>
<beans:property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<beans:property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<beans:property name="privateKeyPassphrase" value="ghj"/>
<beans:property name="password" value="hello"/>
Expand All @@ -30,17 +22,17 @@
</beans:bean>

<sftp:inbound-channel-adapter id="sftpAdapterNoAutoCreate"
channel="requestChannel"
session-factory="sftpSessionFactory"
filter="filter"
remote-directory="/foo"
local-directory="file:foo"
auto-create-local-directory="false"
delete-remote-files="false">
channel="requestChannel"
session-factory="sftpSessionFactory"
filter="filter"
remote-directory="/foo"
local-directory="file:foo"
auto-create-local-directory="false"
delete-remote-files="false">
<poller fixed-rate="1000"/>
</sftp:inbound-channel-adapter>

<beans:bean id="filter" class="org.springframework.integration.sftp.filters.SftpPatternMatchingFileListFilter">
<beans:bean id="filter" class="org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter">
<beans:constructor-arg value="."/>
</beans:bean>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<beans:bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.SimpleSftpSessionFactory">
<beans:property name="host" value="loclahost"/>
<beans:property name="knownHosts" value="local, foo.com, bar.foo"/>
<beans:property name="knownHostsResource" value="local, foo.com, bar.foo"/>
<beans:property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<beans:property name="privateKeyPassphrase" value="ghj"/>
<beans:property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

<beans:bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<beans:property name="host" value="loclahost"/>
<beans:property name="knownHosts" value="local, foo.com, bar.foo"/>
<beans:property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<beans:property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftp_rsa"/>
<beans:property name="privateKeyPassphrase" value="ghj"/>
<beans:property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,17 @@
xmlns="http://www.springframework.org/schema/integration"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tool https://www.springframework.org/schema/tool/spring-tool.xsd
http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/integration/sftp https://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">

<channel id="inboundFilesChannel"/>

<beans:bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<beans:property name="host" value="loclahost"/>
<beans:property name="knownHosts" value="local, foo.com, bar.foo"/>
<beans:property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<beans:property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<beans:property name="privateKeyPassphrase" value="ghj"/>
<beans:property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="knownHosts" value="local, foo.com, bar.foo"/>
<property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<property name="privateKeyPassphrase" value="ghj"/>
<property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.SimpleSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="knownHosts" value="local, foo.com, bar.foo"/>
<property name="knownHostsResource" value="local, foo.com, bar.foo"/>
<property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<property name="privateKeyPassphrase" value="ghj"/>
<property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="knownHosts" value="local, foo.com, bar.foo"/>
<property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<property name="privateKeyPassphrase" value="ghj"/>
<property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="knownHosts" value="local, foo.com, bar.foo"/>
<property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftpTest"/>
<property name="privateKeyPassphrase" value="ghj"/>
<property name="password" value="hello"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="loclahost"/>
<property name="knownHosts" value="local, foo.com, bar.foo"/>
<property name="knownHostsResource"
value="#{ new org.springframework.core.io.ByteArrayResource('local, foo.com, bar.foo'.bytes)}"/>
<property name="privateKey" value="classpath:org/springframework/integration/sftp/config/sftp_rsa"/>
<property name="privateKeyPassphrase" value="ghj"/>
<property name="password" value="hello"/>
Expand Down
4 changes: 2 additions & 2 deletions src/reference/asciidoc/sftp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Required.

`hostKeyAlias`::Sets the host key alias, which is used when comparing the host key to the known hosts list.

`knownHosts`::Specifies the filename that used for a host key repository.
`knownHostsResource`::Specifies the file resource that used for a host key repository.
The file has the same format as OpenSSH's `known_hosts` file and is required and must be pre-populated if `allowUnknownKeys` is false.

`password`::The password to authenticate against the remote host.
Expand Down Expand Up @@ -163,7 +163,7 @@ If `false`, a pre-populated `knownHosts` file is required.
In particular, `promptYesNo()` is invoked when an unknown (or changed) host key is received.
See also <<sftp-unk-keys,`allowUnknownKeys`>>.
When you provide a `UserInfo`, the `password` and private key `passphrase` are obtained from it, and you cannot set discrete
`password` and `privateKeyPassprase` properties.
`password` and `privateKeyPassphrase` properties.

[[sftp-proxy-factory-bean]]
=== Proxy Factory Bean
Expand Down

0 comments on commit 6b82681

Please sign in to comment.