Skip to content

Commit b06d523

Browse files
committed
[JENKINS-48232] Use of reflection for sshd-core library
1 parent 4f48419 commit b06d523

File tree

7 files changed

+484
-149
lines changed

7 files changed

+484
-149
lines changed

Jenkinsfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
buildPlugin()
1+
buildPlugin(jenkinsVersions: [null, '2.89.1'])

pom.xml

+2-8
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@
6666
</scm>
6767

6868
<properties>
69-
<jenkins.version>2.7.1</jenkins.version>
70-
<java.level>7</java.level>
69+
<jenkins.version>1.609</jenkins.version>
70+
<java.level>6</java.level>
7171
</properties>
7272

7373
<repositories>
@@ -99,12 +99,6 @@
9999
</dependency>
100100
<!-- jenkins dependencies -->
101101
<!-- test dependencies -->
102-
<dependency>
103-
<groupId>org.apache.sshd</groupId>
104-
<artifactId>sshd-core</artifactId>
105-
<version>1.6.0</version>
106-
<scope>test</scope>
107-
</dependency>
108102
</dependencies>
109103

110104
</project>

src/main/java/com/cloudbees/jenkins/plugins/sshcredentials/SSHAuthenticator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public static <C, U extends StandardUsernameCredentials> SSHAuthenticator<C, U>
232232
*/
233233
private static List<SSHAuthenticatorFactory> lookupFactories() {
234234
// TODO once Jenkins core has a class that can be used to detect running on build agent use that to gate instead
235-
return Jenkins.getInstanceOrNull() == null ? null : ExtensionList.lookup(SSHAuthenticatorFactory.class);
235+
return Jenkins.getInstance() == null ? null : ExtensionList.lookup(SSHAuthenticatorFactory.class);
236236
}
237237

238238
/**

src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPasswordAuthenticatorTest.java

+116-31
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,15 @@
3131
import com.jcraft.jsch.JSch;
3232
import com.jcraft.jsch.UserInfo;
3333
import hudson.model.Items;
34-
import org.apache.sshd.server.SshServer;
35-
import org.apache.sshd.common.NamedFactory;
36-
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
37-
import org.apache.sshd.server.auth.UserAuth;
38-
import org.apache.sshd.server.auth.password.UserAuthPasswordFactory;
39-
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
40-
import org.apache.sshd.server.session.ServerSession;
4134
import org.junit.After;
4235
import org.junit.Before;
4336
import org.junit.Rule;
4437
import org.junit.Test;
4538
import org.jvnet.hudson.test.JenkinsRule;
4639

40+
import java.lang.reflect.InvocationTargetException;
4741
import java.util.Arrays;
42+
import java.util.List;
4843
import java.util.concurrent.TimeUnit;
4944
import java.util.logging.Level;
5045
import java.util.logging.Logger;
@@ -96,18 +91,21 @@ public void setUp() throws Exception {
9691

9792
@Test
9893
public void testPassword() throws Exception {
99-
SshServer sshd = SshServer.setUpDefaultServer();
100-
sshd.setPort(0);
101-
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
102-
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
103-
public boolean authenticate(String username, String password, ServerSession session) {
104-
return "foomanchu".equals(password);
105-
}
106-
});
107-
sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPasswordFactory()));
94+
Object sshd = newDefaultSshServer();
95+
Class keyPairProviderClass = newKeyPairProviderClass();
96+
Object provider = newProvider();
97+
Class authenticatorClass = newAuthenticatorClass();
98+
Object authenticator = newAuthenticator(authenticatorClass);
99+
Object factory = newFactory();
100+
101+
invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0});
102+
invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider});
103+
invoke(sshd, "setPasswordAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator});
104+
invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)});
108105
try {
109-
sshd.start();
110-
connector = new JSchConnector(user.getUsername(),"localhost", sshd.getPort());
106+
invoke(sshd, "start", null, null);
107+
int port = (Integer)invoke(sshd, "getPort", null, null);
108+
connector = new JSchConnector(user.getUsername(),"localhost", port);
111109
JSchSSHPasswordAuthenticator instance = new JSchSSHPasswordAuthenticator(connector, user);
112110
assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.BEFORE_CONNECT));
113111
assertThat(instance.canAuthenticate(), is(true));
@@ -119,7 +117,7 @@ public boolean authenticate(String username, String password, ServerSession sess
119117
assertThat(connector.getSession().isConnected(), is(true));
120118
} finally {
121119
try {
122-
sshd.stop(true);
120+
invoke(sshd, "stop", new Class[] {Boolean.TYPE}, new Object[] {true});
123121
} catch (Throwable t) {
124122
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Problems shutting down ssh server", t);
125123
}
@@ -128,18 +126,21 @@ public boolean authenticate(String username, String password, ServerSession sess
128126

129127
@Test
130128
public void testFactory() throws Exception {
131-
SshServer sshd = SshServer.setUpDefaultServer();
132-
sshd.setPort(0);
133-
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
134-
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
135-
public boolean authenticate(String username, String password, ServerSession session) {
136-
return "foomanchu".equals(password);
137-
}
138-
});
139-
sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPasswordFactory()));
129+
Object sshd = newDefaultSshServer();
130+
Class keyPairProviderClass = newKeyPairProviderClass();
131+
Object provider = newProvider();
132+
Class authenticatorClass = newAuthenticatorClass();
133+
Object authenticator = newAuthenticator(authenticatorClass);
134+
Object factory = newFactory();
135+
136+
invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0});
137+
invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider});
138+
invoke(sshd, "setPasswordAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator});
139+
invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)});
140140
try {
141-
sshd.start();
142-
connector = new JSchConnector(user.getUsername(),"localhost", sshd.getPort());
141+
invoke(sshd, "start", null, null);
142+
int port = (Integer)invoke(sshd, "getPort", null, null);
143+
connector = new JSchConnector(user.getUsername(),"localhost", port);
143144
SSHAuthenticator instance = SSHAuthenticator.newInstance(connector, user);
144145
assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.BEFORE_CONNECT));
145146
assertThat(instance.canAuthenticate(), is(true));
@@ -151,7 +152,7 @@ public boolean authenticate(String username, String password, ServerSession sess
151152
assertThat(connector.getSession().isConnected(), is(true));
152153
} finally {
153154
try {
154-
sshd.stop(true);
155+
invoke(sshd, "stop", new Class[] {Boolean.TYPE}, new Object[] {true});
155156
} catch (Throwable t) {
156157
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Problems shutting down ssh server", t);
157158
}
@@ -185,4 +186,88 @@ public HostKey[] getHostKey(String host, String type) {
185186
return new HostKey[0];
186187
}
187188
}
189+
190+
191+
192+
private Object invoke(Object target, String methodName, Class[] parameterTypes, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
193+
return target.getClass().getMethod(methodName, parameterTypes).invoke(target, args);
194+
}
195+
196+
private Object newDefaultSshServer() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
197+
Object sshd = null;
198+
Class sshdClass;
199+
try {
200+
sshdClass = Class.forName("org.apache.sshd.SshServer");
201+
} catch (ClassNotFoundException e) {
202+
sshdClass = Class.forName("org.apache.sshd.server.SshServer");
203+
}
204+
205+
sshd = sshdClass.getDeclaredMethod("setUpDefaultServer", null).invoke(null);
206+
assertNotNull(sshd);
207+
208+
return sshd;
209+
}
210+
211+
private Class newKeyPairProviderClass() throws ClassNotFoundException {
212+
Class keyPairProviderClass;
213+
try {
214+
keyPairProviderClass = Class.forName("org.apache.sshd.common.KeyPairProvider");
215+
} catch (ClassNotFoundException e) {
216+
keyPairProviderClass = Class.forName("org.apache.sshd.common.keyprovider.KeyPairProvider");
217+
}
218+
219+
return keyPairProviderClass;
220+
}
221+
222+
private Object newProvider() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
223+
Class providerClass = Class.forName("org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider");
224+
Object provider = providerClass.getConstructor().newInstance();
225+
assertNotNull(provider);
226+
227+
return provider;
228+
}
229+
private Class newAuthenticatorClass() throws ClassNotFoundException {
230+
Class authenticatorClass;
231+
try {
232+
authenticatorClass = Class.forName("org.apache.sshd.server.auth.password.PasswordAuthenticator");
233+
} catch(ClassNotFoundException e) {
234+
authenticatorClass = Class.forName("org.apache.sshd.server.PasswordAuthenticator");
235+
}
236+
237+
return authenticatorClass;
238+
}
239+
240+
private Object newAuthenticator(Class authenticatorClass) throws ClassNotFoundException, IllegalArgumentException {
241+
Object authenticator = java.lang.reflect.Proxy.newProxyInstance(
242+
authenticatorClass.getClassLoader(),
243+
new java.lang.Class[]{authenticatorClass},
244+
new java.lang.reflect.InvocationHandler() {
245+
246+
@Override
247+
public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws java.lang.Throwable {
248+
if (method.getName().equals("authenticate")) {
249+
return "foomanchu".equals(args[1]);
250+
}
251+
252+
return null;
253+
}
254+
});
255+
assertNotNull(authenticator);
256+
return authenticator;
257+
}
258+
259+
private Object newFactory() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
260+
Object factory = null;
261+
Class factoryClass;
262+
try {
263+
factoryClass = Class.forName("org.apache.sshd.server.auth.UserAuthPassword$Factory");
264+
} catch (ClassNotFoundException e) {
265+
factoryClass = Class.forName("org.apache.sshd.server.auth.password.UserAuthPasswordFactory");
266+
}
267+
268+
factory = factoryClass.getConstructor().newInstance();
269+
270+
assertNotNull(factory);
271+
return factory;
272+
}
188273
}

0 commit comments

Comments
 (0)