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:
Gary Russell
2015-08-08 11:16:00 -04:00
committed by Artem Bilan
parent 56bfe6b0ac
commit e82bfdc9a6
8 changed files with 158 additions and 98 deletions

View File

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

View File

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

View File

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

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

View File

@@ -0,0 +1 @@
AAAAB3NzaC1yc2EAAAADAQABAAABAQC6MIzgyVi8G1+HRhFHPWRH+3w/8/uxtiuIfb4puVPjHI53Lvf5odzfhv0T6Z2/jSXmI3I6dpjbsgiptdCTX4kqUFLXxkuJR4LHatNtgO1w32aVIdAvfj7KtrL3SmP2XWqQGVcUWHEn2H1RHFHKdC6ArYFb1X8p5N/BHSQjuttaeVi9FsDxvC5euIbtDEEJmmvjjfWlI1m/6qCqMYxDWA9i9APU/rB0QwFNUQ6HuZ2QzEaU/hQMGmqgW5o1I/W8JR0bqis8wZQDLv1fwCkXpWG5BAuiJH+FJMxRAkfEMBpVwO7Sl0ufePVuSM2BMAAe+4a75sVp8ahbOId6y0GUTeJl