package alien4cloud.it.provider.util; import java.io.FileReader; import java.io.IOException; import java.security.KeyPair; import java.security.Security; import lombok.extern.slf4j.Slf4j; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; import org.apache.sshd.client.ScpClient; import org.apache.sshd.client.future.AuthFuture; import org.apache.sshd.common.future.SshFutureListener; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; @Slf4j public class SSHUtil { private static KeyPair loadKeyPair(String pemFile) { try { Security.addProvider(new BouncyCastleProvider()); PEMParser pemParser = new PEMParser(new FileReader(pemFile)); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); Object object = pemParser.readObject(); return converter.getKeyPair((PEMKeyPair) object); } catch (Exception e) { log.error("Could not load key pair", e); throw new RuntimeException("Could not load key pair", e); } } private static ClientSession connect(SshClient client, final String user, KeyPair keyPair, final String ip, final int port) throws IOException, InterruptedException { ClientSession session = client.connect(user, ip, port).await().getSession(); int authState = ClientSession.WAIT_AUTH; while ((authState & ClientSession.WAIT_AUTH) != 0) { session.addPublicKeyIdentity(keyPair); log.info("Authenticating to " + user + "@" + ip); AuthFuture authFuture = session.auth(); authFuture.addListener(new SshFutureListener<AuthFuture>() { @Override public void operationComplete(AuthFuture authFuture) { log.info("Authentication completed with " + (authFuture.isSuccess() ? "success" : "failure") + " for " + user + "@" + ip + ":" + port); } }); authState = session.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0); } if ((authState & ClientSession.CLOSED) != 0) { throw new IOException("Authentication failed for " + user + "@" + ip); } return session; } private interface DoWithScpAction { void doScpAction(ScpClient scpClient) throws IOException; } private static void doWithScp(String user, String ip, int port, String pemPath, DoWithScpAction doWithScpAction) throws IOException, InterruptedException { SshClient client = SshClient.setUpDefaultClient(); ClientSession session = null; try { client.start(); session = connect(client, user, loadKeyPair(pemPath), ip, port); ScpClient scpClient = session.createScpClient(); doWithScpAction.doScpAction(scpClient); } finally { if (session != null) { session.close(true); } client.close(true); } } public static void download(String user, String ip, int port, String pemPath, final String remote, final String local) throws IOException, InterruptedException { doWithScp(user, ip, port, pemPath, new DoWithScpAction() { @Override public void doScpAction(ScpClient scpClient) throws IOException { scpClient.download(remote, local, ScpClient.Option.Recursive); } }); } public static void upload(String user, String ip, int port, String pemPath, final String remote, final String local) throws IOException, InterruptedException { doWithScp(user, ip, port, pemPath, new DoWithScpAction() { @Override public void doScpAction(ScpClient scpClient) throws IOException { scpClient.upload(local, remote, ScpClient.Option.Recursive); } }); } }