diff --git a/Jenkinsfile b/Jenkinsfile index a229fa5..75b6296 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1 +1 @@ -buildPlugin() +buildPlugin(jenkinsVersions: [null, '2.89.1']) diff --git a/pom.xml b/pom.xml index 9ec21e9..5185f6e 100644 --- a/pom.xml +++ b/pom.xml @@ -66,8 +66,8 @@ - 2.7.1 - 7 + 1.609 + 6 @@ -99,12 +99,6 @@ - - org.apache.sshd - sshd-core - 1.6.0 - test - diff --git a/src/main/java/com/cloudbees/jenkins/plugins/sshcredentials/SSHAuthenticator.java b/src/main/java/com/cloudbees/jenkins/plugins/sshcredentials/SSHAuthenticator.java index 47f0c72..754d6ac 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/sshcredentials/SSHAuthenticator.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/sshcredentials/SSHAuthenticator.java @@ -232,7 +232,7 @@ public static SSHAuthenticator */ private static List 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); } /** diff --git a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPasswordAuthenticatorTest.java b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPasswordAuthenticatorTest.java index d2c9307..0bc9252 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPasswordAuthenticatorTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPasswordAuthenticatorTest.java @@ -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; @@ -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.>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)); @@ -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); } @@ -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.>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)); @@ -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); } @@ -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; + } } diff --git a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPublicKeyAuthenticatorTest.java b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPublicKeyAuthenticatorTest.java index 1480a05..8abd3e6 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPublicKeyAuthenticatorTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/JSchSSHPublicKeyAuthenticatorTest.java @@ -30,20 +30,13 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.util.Secret; -import org.apache.sshd.server.SshServer; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator; -import org.apache.sshd.server.auth.UserAuth; -import org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory; -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.security.PublicKey; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -137,18 +130,21 @@ public List getPrivateKeys() { @Test public void testAuthenticate() throws Exception { - SshServer sshd = SshServer.setUpDefaultServer(); - sshd.setPort(0); - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider()); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return username.equals("foobar"); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPublicKeyFactory())); + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, "foobar"); + Object factory = newFactory(); + + invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0}); + invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider}); + invoke(sshd, "setPublickeyAuthenticator", 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); JSchSSHPublicKeyAuthenticator instance = new JSchSSHPublicKeyAuthenticator(connector, user); assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.BEFORE_CONNECT)); @@ -161,7 +157,7 @@ public boolean authenticate(String username, PublicKey key, ServerSession sessio 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); } @@ -170,18 +166,21 @@ public boolean authenticate(String username, PublicKey key, ServerSession sessio @Test public void testFactory() throws Exception { - SshServer sshd = SshServer.setUpDefaultServer(); - sshd.setPort(0); - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider()); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return username.equals("foobar"); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPublicKeyFactory())); + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, "foobar"); + Object factory = newFactory(); + + invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0}); + invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider}); + invoke(sshd, "setPublickeyAuthenticator", 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)); @@ -193,10 +192,92 @@ public boolean authenticate(String username, PublicKey key, ServerSession sessio 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); } } } -} + + 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.pubkey.PublickeyAuthenticator"); + } catch(ClassNotFoundException e) { + authenticatorClass = Class.forName("org.apache.sshd.server.PublickeyAuthenticator"); + } + + return authenticatorClass; + } + + private Object newAuthenticator(Class authenticatorClass, final String userName) 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 userName.equals(args[0]); + } + + 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.UserAuthPublicKey$Factory"); + } catch (ClassNotFoundException e) { + factoryClass = Class.forName("org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory"); + } + + factory = factoryClass.getConstructor().newInstance(); + + assertNotNull(factory); + return factory; + }} diff --git a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPasswordAuthenticatorTest.java b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPasswordAuthenticatorTest.java index 234332e..b71a7b9 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPasswordAuthenticatorTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPasswordAuthenticatorTest.java @@ -34,31 +34,27 @@ import hudson.slaves.DumbSlave; import jenkins.security.MasterToSlaveCallable; -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.logging.Level; import java.util.logging.Logger; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; public class TrileadSSHPasswordAuthenticatorTest { private Connection connection; private StandardUsernamePasswordCredentials user; - private SshServer sshd; + private Object sshd; @Rule public JenkinsRule r = new JenkinsRule(); @@ -70,7 +66,7 @@ public void tearDown() throws Exception { } if (sshd!=null) { 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); } @@ -100,8 +96,9 @@ public void setUp() throws Exception { @Test public void testPassword() throws Exception { sshd = createPasswordAuthenticatedSshServer(); - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new NoVerifier()); TrileadSSHPasswordAuthenticator instance = new TrileadSSHPasswordAuthenticator(connection, user); @@ -111,28 +108,32 @@ public void testPassword() throws Exception { assertThat(instance.isAuthenticated(), is(true)); } - private SshServer createPasswordAuthenticatedSshServer() { + private Object createPasswordAuthenticatedSshServer() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, InstantiationException, IllegalAccessException { return createPasswordAuthenticatedSshServer(null); } - private SshServer createPasswordAuthenticatedSshServer(final String username) { - 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 (username == null || username.equals(_username)) && "foomanchu".equals(password); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPasswordFactory())); + private Object createPasswordAuthenticatedSshServer(final String username) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, InstantiationException { + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, username); + 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)}); + return sshd; } @Test public void testFactory() throws Exception { sshd = createPasswordAuthenticatedSshServer(); - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new NoVerifier()); SSHAuthenticator instance = SSHAuthenticator.newInstance(connection, user); assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.AFTER_CONNECT)); @@ -144,15 +145,16 @@ public void testFactory() throws Exception { @Test public void testFactoryAltUsername() throws Exception { sshd = createPasswordAuthenticatedSshServer("bill"); - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new NoVerifier()); SSHAuthenticator instance = SSHAuthenticator.newInstance(connection, user, null); assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.AFTER_CONNECT)); assertThat(instance.canAuthenticate(), is(true)); assertThat(instance.authenticate(), is(false)); assertThat(instance.isAuthenticated(), is(false)); - connection = new Connection("localhost", sshd.getPort()); + connection = new Connection("localhost", port); connection.connect(new NoVerifier()); instance = SSHAuthenticator.newInstance(connection, user, "bill"); assertThat(instance.getAuthenticationMode(), is(SSHAuthenticator.Mode.AFTER_CONNECT)); @@ -166,14 +168,14 @@ public void testFactoryAltUsername() throws Exception { */ @Test public void testSlave() throws Exception { - SshServer sshd = createPasswordAuthenticatedSshServer(); - sshd.start(); + Object sshd = createPasswordAuthenticatedSshServer(); + invoke(sshd, "start", null, null); DumbSlave s = r.createSlave(); Computer c = s.toComputer(); c.connect(false).get(); - final int port = sshd.getPort(); + final int port = (Integer)invoke(sshd, "getPort", null, null); c.getChannel().call(new RemoteConnectionTest(port,user)); } @@ -209,4 +211,87 @@ public Void call() throws Exception { private static final long serialVersionUID = 1L; } + + 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 server = null; + Class serverClass; + try { + serverClass = Class.forName("org.apache.sshd.SshServer"); + } catch (ClassNotFoundException e) { + serverClass = Class.forName("org.apache.sshd.server.SshServer"); + } + + server = serverClass.getDeclaredMethod("setUpDefaultServer", null).invoke(null); + assertNotNull(server); + + return server; + } + + 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, final String userName) 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 (userName == null || userName.equals(args[0])) && "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; + } } diff --git a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPublicKeyAuthenticatorTest.java b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPublicKeyAuthenticatorTest.java index f9c4f74..6e69e3d 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPublicKeyAuthenticatorTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/sshcredentials/impl/TrileadSSHPublicKeyAuthenticatorTest.java @@ -32,20 +32,14 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.util.Secret; -import org.apache.sshd.server.SshServer; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator; -import org.apache.sshd.server.auth.UserAuth; -import org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory; -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.security.PublicKey; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -53,6 +47,7 @@ import java.util.logging.Logger; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; public class TrileadSSHPublicKeyAuthenticatorTest { @@ -137,18 +132,23 @@ public List getPrivateKeys() { @Test public void testAuthenticate() throws Exception { - SshServer sshd = SshServer.setUpDefaultServer(); - sshd.setPort(0); - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider()); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return username.equals("foobar"); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPublicKeyFactory())); + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, "foobar"); + Object factory = newFactory(); + assertNotNull(factory); + + invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0}); + invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider}); + invoke(sshd, "setPublickeyAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator}); + invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)}); + try { - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new ServerHostKeyVerifier() { public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) @@ -164,7 +164,7 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK assertThat(instance.isAuthenticated(), 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); } @@ -173,18 +173,22 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK @Test public void testFactory() throws Exception { - SshServer sshd = SshServer.setUpDefaultServer(); - sshd.setPort(0); - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider()); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return username.equals("foobar"); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPublicKeyFactory())); + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, "foobar"); + Object factory = newFactory(); + assertNotNull(factory); + + invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0}); + invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider}); + invoke(sshd, "setPublickeyAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator}); + invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)}); try { - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new ServerHostKeyVerifier() { public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) @@ -199,7 +203,7 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK assertThat(instance.isAuthenticated(), 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); } @@ -208,18 +212,21 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK @Test public void testAltUsername() throws Exception { - SshServer sshd = SshServer.setUpDefaultServer(); - sshd.setPort(0); - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider()); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return username.equals("bill"); - } - }); - sshd.setUserAuthFactories(Arrays.>asList(new UserAuthPublicKeyFactory())); + Object sshd = newDefaultSshServer(); + Class keyPairProviderClass = newKeyPairProviderClass(); + Object provider = newProvider(); + Class authenticatorClass = newAuthenticatorClass(); + Object authenticator = newAuthenticator(authenticatorClass, "bill"); + Object factory = newFactory(); + + invoke(sshd, "setPort", new Class[] {Integer.TYPE}, new Object[] {0}); + invoke(sshd, "setKeyPairProvider", new Class[] {keyPairProviderClass}, new Object[] {provider}); + invoke(sshd, "setPublickeyAuthenticator", new Class[] {authenticatorClass}, new Object[] {authenticator}); + invoke(sshd, "setUserAuthFactories", new Class[] {List.class}, new Object[] {Arrays.asList(factory)}); try { - sshd.start(); - connection = new Connection("localhost", sshd.getPort()); + invoke(sshd, "start", null, null); + int port = (Integer)invoke(sshd, "getPort", null, null); + connection = new Connection("localhost", port); connection.connect(new ServerHostKeyVerifier() { public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) @@ -232,7 +239,7 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK assertThat(instance.canAuthenticate(), is(true)); assertThat(instance.authenticate(), is(false)); assertThat(instance.isAuthenticated(), is(false)); - connection = new Connection("localhost", sshd.getPort()); + connection = new Connection("localhost", port); connection.connect(new ServerHostKeyVerifier() { public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) @@ -247,10 +254,93 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK assertThat(instance.isAuthenticated(), 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); } } } + + 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.pubkey.PublickeyAuthenticator"); + } catch(ClassNotFoundException e) { + authenticatorClass = Class.forName("org.apache.sshd.server.PublickeyAuthenticator"); + } + + return authenticatorClass; + } + + private Object newAuthenticator(Class authenticatorClass, final String userName) 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 userName.equals(args[0]); + } + + 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.UserAuthPublicKey$Factory"); + } catch (ClassNotFoundException e) { + factoryClass = Class.forName("org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory"); + } + + factory = factoryClass.getConstructor().newInstance(); + + assertNotNull(factory); + return factory; + } }