Skip to content

Commit

Permalink
[JENKINS-48232] Use of reflection for sshd-core library
Browse files Browse the repository at this point in the history
  • Loading branch information
fcojfernandez committed Jan 12, 2018
1 parent 4f48419 commit b06d523
Show file tree
Hide file tree
Showing 7 changed files with 484 additions and 149 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
buildPlugin()
buildPlugin(jenkinsVersions: [null, '2.89.1'])
10 changes: 2 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@
</scm>

<properties>
<jenkins.version>2.7.1</jenkins.version>
<java.level>7</java.level>
<jenkins.version>1.609</jenkins.version>
<java.level>6</java.level>
</properties>

<repositories>
Expand Down Expand Up @@ -99,12 +99,6 @@
</dependency>
<!-- jenkins dependencies -->
<!-- test dependencies -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>

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

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,15 @@
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.UserInfo;
import hudson.model.Items;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.auth.UserAuth;
import org.apache.sshd.server.auth.password.UserAuthPasswordFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -96,18 +91,21 @@ public void setUp() throws Exception {

@Test
public void testPassword() throws Exception {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(0);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(String username, String password, ServerSession session) {
return "foomanchu".equals(password);
}
});
sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPasswordFactory()));
Object sshd = newDefaultSshServer();
Class keyPairProviderClass = newKeyPairProviderClass();
Object provider = newProvider();
Class authenticatorClass = newAuthenticatorClass();
Object authenticator = newAuthenticator(authenticatorClass);
Object factory = newFactory();

invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0});
invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider});
invoke(sshd, "setPasswordAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator});
invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)});
try {
sshd.start();
connector = new JSchConnector(user.getUsername(),"localhost", sshd.getPort());
invoke(sshd, "start", null, null);
int port = (Integer)invoke(sshd, "getPort", null, null);
connector = new JSchConnector(user.getUsername(),"localhost", port);
JSchSSHPasswordAuthenticator instance = new JSchSSHPasswordAuthenticator(connector, user);
assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.BEFORE_CONNECT));
assertThat(instance.canAuthenticate(), is(true));
Expand All @@ -119,7 +117,7 @@ public boolean authenticate(String username, String password, ServerSession sess
assertThat(connector.getSession().isConnected(), is(true));
} finally {
try {
sshd.stop(true);
invoke(sshd, "stop", new Class[] {Boolean.TYPE}, new Object[] {true});
} catch (Throwable t) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Problems shutting down ssh server", t);
}
Expand All @@ -128,18 +126,21 @@ public boolean authenticate(String username, String password, ServerSession sess

@Test
public void testFactory() throws Exception {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(0);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(String username, String password, ServerSession session) {
return "foomanchu".equals(password);
}
});
sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPasswordFactory()));
Object sshd = newDefaultSshServer();
Class keyPairProviderClass = newKeyPairProviderClass();
Object provider = newProvider();
Class authenticatorClass = newAuthenticatorClass();
Object authenticator = newAuthenticator(authenticatorClass);
Object factory = newFactory();

invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0});
invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider});
invoke(sshd, "setPasswordAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator});
invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)});
try {
sshd.start();
connector = new JSchConnector(user.getUsername(),"localhost", sshd.getPort());
invoke(sshd, "start", null, null);
int port = (Integer)invoke(sshd, "getPort", null, null);
connector = new JSchConnector(user.getUsername(),"localhost", port);
SSHAuthenticator instance = SSHAuthenticator.newInstance(connector, user);
assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.BEFORE_CONNECT));
assertThat(instance.canAuthenticate(), is(true));
Expand All @@ -151,7 +152,7 @@ public boolean authenticate(String username, String password, ServerSession sess
assertThat(connector.getSession().isConnected(), is(true));
} finally {
try {
sshd.stop(true);
invoke(sshd, "stop", new Class[] {Boolean.TYPE}, new Object[] {true});
} catch (Throwable t) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Problems shutting down ssh server", t);
}
Expand Down Expand Up @@ -185,4 +186,88 @@ public HostKey[] getHostKey(String host, String type) {
return new HostKey[0];
}
}



private Object invoke(Object target, String methodName, Class[] parameterTypes, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
return target.getClass().getMethod(methodName, parameterTypes).invoke(target, args);
}

private Object newDefaultSshServer() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object sshd = null;
Class sshdClass;
try {
sshdClass = Class.forName("org.apache.sshd.SshServer");
} catch (ClassNotFoundException e) {
sshdClass = Class.forName("org.apache.sshd.server.SshServer");
}

sshd = sshdClass.getDeclaredMethod("setUpDefaultServer", null).invoke(null);
assertNotNull(sshd);

return sshd;
}

private Class newKeyPairProviderClass() throws ClassNotFoundException {
Class keyPairProviderClass;
try {
keyPairProviderClass = Class.forName("org.apache.sshd.common.KeyPairProvider");
} catch (ClassNotFoundException e) {
keyPairProviderClass = Class.forName("org.apache.sshd.common.keyprovider.KeyPairProvider");
}

return keyPairProviderClass;
}

private Object newProvider() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class providerClass = Class.forName("org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider");
Object provider = providerClass.getConstructor().newInstance();
assertNotNull(provider);

return provider;
}
private Class newAuthenticatorClass() throws ClassNotFoundException {
Class authenticatorClass;
try {
authenticatorClass = Class.forName("org.apache.sshd.server.auth.password.PasswordAuthenticator");
} catch(ClassNotFoundException e) {
authenticatorClass = Class.forName("org.apache.sshd.server.PasswordAuthenticator");
}

return authenticatorClass;
}

private Object newAuthenticator(Class authenticatorClass) throws ClassNotFoundException, IllegalArgumentException {
Object authenticator = java.lang.reflect.Proxy.newProxyInstance(
authenticatorClass.getClassLoader(),
new java.lang.Class[]{authenticatorClass},
new java.lang.reflect.InvocationHandler() {

@Override
public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws java.lang.Throwable {
if (method.getName().equals("authenticate")) {
return "foomanchu".equals(args[1]);
}

return null;
}
});
assertNotNull(authenticator);
return authenticator;
}

private Object newFactory() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Object factory = null;
Class factoryClass;
try {
factoryClass = Class.forName("org.apache.sshd.server.auth.UserAuthPassword$Factory");
} catch (ClassNotFoundException e) {
factoryClass = Class.forName("org.apache.sshd.server.auth.password.UserAuthPasswordFactory");
}

factory = factoryClass.getConstructor().newInstance();

assertNotNull(factory);
return factory;
}
}
Loading

0 comments on commit b06d523

Please sign in to comment.