I am attempting to build an application that makes use of Spring Boot and Integration to retrieve files from a remote system over SSH. It works just fine if I set the allowUnknownKeys
property of the SessionFactory to true.
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost("x");
factory.setPort(22);
factory.setUser("x");
factory.setPassword("x");
factory.setAllowUnknownKeys(true);
// factory.setHostKeyAlias("x");
// factory.setKnownHosts(
// System.getProperty("user.home") + File.separator + ".ssh" + File.separator + "known_hosts");
return new CachingSessionFactory<LsEntry>(factory);
}
However, if I set allowUnknownKeys
to false and uncomment out the lines in the snippet above, a connection cannot be established.
2019-01-21 08:55:05.536 ERROR 10680 --- [ask-scheduler-1] o.s.integration.handler.LoggingHandler : org.springframework.messaging.MessagingException: Problem occurred while synchronizing 'sftp-outbound' to local directory; nested exception is org.springframework.messaging.MessagingException: Failed to execute on session; nested exception is org.springframework.integration.util.PoolItemNotAvailableException: Failed to obtain pooled item
The underlying cause is the fact that the "authenticity of the host" cannot be established, and it is wanting me to give permission to establish the connection. I understand this. However, my problem is why it is not reading/parsing the the known_hosts file correctly? The one I am passing to it is the one automatically generated and it works fine when I ssh into a system through the command line. Using breakpoints, I have verified that the application is finding and reading the correct known_hosts
file. I can use the exact same credentials and connect through a bash shell without any prompt concerning the authenticity of the host.
What am I missing?
Thanks.
Interesting; I just tested it mac to mac and had the same problem - I debugged the JSCH client and it finds the key ok, but the type doesn't match - in my known_hosts file, the type is ecdsa-sha2-nistp256
(type 3) but the key returned by the key exchange is reported as type 2 (ssh-rsa
).
I solved it with help from this answer...
Properties sessionConfig = new Properties();
sessionConfig.setProperty("server_host_key", "ecdsa-sha2-nistp256");
factory.setSessionConfig(sessionConfig);
Or you can add the ssh-rsa key to the known_hosts as is described in the links there.
Confirmed that rebuilding known_hosts with
ssh -o HostKeyAlgorithms=ssh-rsa <host>
(or ssh-keyscan
) works too.