Skip to content

Commit ed1d845

Browse files
VaishKumbharVaishnavi Kumbhar
andauthored
Add SFTP password authentication tests for Commons VFS2 (#754)
* Add SFTP password authentication tests for Commons VFS2 * Migrate SFTP test infrastructure from Apache MINA SSHD 0.x to 3.x API * Migrate SFTP test infrastructure from Apache MINA SSHD 0.x to 3.x API --------- Co-authored-by: Vaishnavi Kumbhar <vaishkum@amdocs.com>
1 parent aa91b87 commit ed1d845

4 files changed

Lines changed: 351 additions & 292 deletions

File tree

commons-vfs2/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,15 @@
116116
<artifactId>log4j-core</artifactId>
117117
<scope>test</scope>
118118
</dependency>
119-
<!-- Test SFTP with Apache SHHd Server (MINA) -->
119+
<!-- Test SFTP with Apache SSHd Server (MINA) -->
120120
<dependency>
121121
<groupId>org.apache.sshd</groupId>
122122
<artifactId>sshd-core</artifactId>
123123
<scope>test</scope>
124124
</dependency>
125125
<dependency>
126-
<groupId>org.bouncycastle</groupId>
127-
<artifactId>bcprov-jdk16</artifactId>
126+
<groupId>org.apache.sshd</groupId>
127+
<artifactId>sshd-sftp</artifactId>
128128
<scope>test</scope>
129129
</dependency>
130130
<dependency>
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.vfs2.provider.sftp;
19+
20+
import static org.apache.commons.vfs2.VfsTestUtils.getTestDirectoryFile;
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
import static org.junit.jupiter.api.Assertions.assertThrows;
24+
import static org.junit.jupiter.api.Assertions.assertTrue;
25+
26+
import java.io.File;
27+
import java.nio.file.Files;
28+
import java.nio.file.Path;
29+
import java.time.Duration;
30+
import java.util.Collections;
31+
32+
import org.apache.commons.vfs2.FileObject;
33+
import org.apache.commons.vfs2.FileSystemException;
34+
import org.apache.commons.vfs2.FileSystemOptions;
35+
import org.apache.commons.vfs2.FileType;
36+
import org.apache.commons.vfs2.auth.StaticUserAuthenticator;
37+
import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;
38+
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
39+
import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider;
40+
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
41+
import org.apache.sshd.server.SshServer;
42+
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
43+
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
44+
import org.junit.jupiter.api.AfterAll;
45+
import org.junit.jupiter.api.BeforeAll;
46+
import org.junit.jupiter.api.Test;
47+
48+
import com.jcraft.jsch.TestIdentityRepositoryFactory;
49+
50+
/**
51+
* Tests SFTP password authentication using {@link StaticUserAuthenticator}.
52+
* <p>
53+
* Verifies that credentials supplied via {@link DefaultFileSystemConfigBuilder#setUserAuthenticator}
54+
* are correctly propagated to the SFTP server.
55+
* </p>
56+
*/
57+
public class SftpPasswordAuthTest {
58+
59+
private static final String TEST_USERNAME = "testuser";
60+
private static final String TEST_PASSWORD = "testpass";
61+
62+
private static SshServer sshServer;
63+
private static int serverPort;
64+
private static DefaultFileSystemManager manager;
65+
66+
@BeforeAll
67+
static void setUp() throws Exception {
68+
sshServer = SshServer.setUpDefaultServer();
69+
sshServer.setPort(0);
70+
71+
final Path tmpKeyFile = Files.createTempFile("sshd-test-key", ".ser");
72+
tmpKeyFile.toFile().deleteOnExit();
73+
final SimpleGeneratorHostKeyProvider keyProvider = new SimpleGeneratorHostKeyProvider(tmpKeyFile);
74+
keyProvider.setAlgorithm("RSA");
75+
sshServer.setKeyPairProvider(keyProvider);
76+
77+
sshServer.setPasswordAuthenticator(
78+
(user, pass, session) -> TEST_USERNAME.equals(user) && TEST_PASSWORD.equals(pass));
79+
80+
sshServer.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
81+
82+
final File homeDir = getTestDirectoryFile();
83+
sshServer.setFileSystemFactory(
84+
new VirtualFileSystemFactory(homeDir.toPath().toAbsolutePath()));
85+
86+
sshServer.start();
87+
serverPort = sshServer.getPort();
88+
89+
manager = new DefaultFileSystemManager();
90+
manager.addProvider("sftp", new SftpFileProvider());
91+
manager.addProvider("file", new DefaultLocalFileProvider());
92+
manager.init();
93+
}
94+
95+
@AfterAll
96+
static void tearDown() throws Exception {
97+
if (manager != null) {
98+
try {
99+
manager.close();
100+
} catch (final Exception e) {
101+
// ignore
102+
}
103+
}
104+
if (sshServer != null) {
105+
stopServerWithTimeout(5000);
106+
}
107+
}
108+
109+
private static void stopServerWithTimeout(final long timeoutMs) {
110+
final Thread stopThread = new Thread(() -> {
111+
try {
112+
sshServer.close();
113+
} catch (final Exception e) {
114+
// ignore
115+
}
116+
}, "sshd-stop");
117+
stopThread.setDaemon(true);
118+
stopThread.start();
119+
try {
120+
stopThread.join(timeoutMs);
121+
} catch (final InterruptedException e) {
122+
Thread.currentThread().interrupt();
123+
}
124+
}
125+
126+
private static String baseUri() {
127+
return String.format("sftp://%s@localhost:%d", TEST_USERNAME, serverPort);
128+
}
129+
130+
private FileSystemOptions authOptions() throws FileSystemException {
131+
final FileSystemOptions opts = new FileSystemOptions();
132+
final StaticUserAuthenticator auth = new StaticUserAuthenticator(null, TEST_USERNAME, TEST_PASSWORD);
133+
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
134+
configureSftpOptions(opts);
135+
return opts;
136+
}
137+
138+
private static void configureSftpOptions(final FileSystemOptions opts) throws FileSystemException {
139+
final SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance();
140+
builder.setStrictHostKeyChecking(opts, "no");
141+
builder.setUserInfo(opts, new TrustEveryoneUserInfo());
142+
builder.setIdentityRepositoryFactory(opts, new TestIdentityRepositoryFactory());
143+
builder.setConnectTimeout(opts, Duration.ofSeconds(60));
144+
builder.setSessionTimeout(opts, Duration.ofSeconds(60));
145+
}
146+
147+
@Test
148+
void testResolveFile() throws FileSystemException {
149+
final FileSystemOptions opts = authOptions();
150+
try (FileObject file = manager.resolveFile(baseUri() + "/read-tests/file1.txt", opts)) {
151+
assertNotNull(file);
152+
assertTrue(file.exists(), "file1.txt should exist");
153+
assertEquals(FileType.FILE, file.getType());
154+
assertNotNull(file.getContent(), "Content should be readable when credentials are correct");
155+
}
156+
}
157+
158+
@Test
159+
void testResolveFolder() throws FileSystemException {
160+
final FileSystemOptions opts = authOptions();
161+
try (FileObject folder = manager.resolveFile(baseUri() + "/read-tests", opts)) {
162+
assertNotNull(folder);
163+
assertTrue(folder.exists(), "read-tests folder should exist");
164+
}
165+
}
166+
167+
@Test
168+
void testResolveFolderWithTrailingSlash() throws FileSystemException {
169+
final FileSystemOptions opts = authOptions();
170+
try (FileObject folder = manager.resolveFile(baseUri() + "/read-tests/", opts)) {
171+
assertNotNull(folder);
172+
assertTrue(folder.exists(), "read-tests/ folder should exist");
173+
}
174+
}
175+
176+
@Test
177+
void testWrongCredentialsThrowsException() throws FileSystemException {
178+
final FileSystemOptions opts = new FileSystemOptions();
179+
final StaticUserAuthenticator auth = new StaticUserAuthenticator(null, "wronguser", "wrongpassword");
180+
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
181+
configureSftpOptions(opts);
182+
183+
final String wrongUserUri = String.format("sftp://wronguser@localhost:%d/read-tests/file1.txt", serverPort);
184+
assertThrows(FileSystemException.class, () -> {
185+
try (FileObject file = manager.resolveFile(wrongUserUri, opts)) {
186+
file.exists();
187+
}
188+
}, "Expected FileSystemException when accessing a resource with wrong credentials");
189+
}
190+
}

0 commit comments

Comments
 (0)