From 161df8a94bb3b0c34ed16fd4fdba078bd1eeef9a Mon Sep 17 00:00:00 2001 From: Patrick Brady Date: Wed, 13 Dec 2017 11:14:21 -0800 Subject: Second part of onap rename This is the second commit of the rename. The folder structure is renamed for appc-adapters and appc-config in this commit. Change-Id: Iaa2b8c937ff1ca1b5d1178128961fb115ee65d9b Signed-off-by: Patrick Brady Issue-ID: APPC-13 --- .../onap/appc/adapter/ssh/sshd/SshAdapterSshd.java | 36 +++ .../appc/adapter/ssh/sshd/SshConnectionSshd.java | 236 +++++++++++++++++++ .../adapter/ssh/sshd/SshdDataAccessService.java | 106 +++++++++ .../appc/adapter/ssh/sshd/SshAdapterSshd.java | 36 --- .../appc/adapter/ssh/sshd/SshConnectionSshd.java | 236 ------------------- .../adapter/ssh/sshd/SshdDataAccessService.java | 106 --------- .../appc/adapter/ssh/sshd/SshAdapterSample.java | 59 +++++ .../onap/appc/adapter/ssh/sshd/SshAdapterTest.java | 250 +++++++++++++++++++++ .../appc/adapter/ssh/sshd/SshAdapterSample.java | 59 ----- .../appc/adapter/ssh/sshd/SshAdapterTest.java | 250 --------------------- 10 files changed, 687 insertions(+), 687 deletions(-) create mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSshd.java create mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshConnectionSshd.java create mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshdDataAccessService.java delete mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSshd.java delete mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java delete mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java create mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSample.java create mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterTest.java delete mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSample.java delete mode 100644 appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java (limited to 'appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src') diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSshd.java new file mode 100644 index 000000000..a5bbe34e2 --- /dev/null +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSshd.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.ssh.sshd; + +import org.onap.appc.adapter.ssh.SshAdapter; +import org.onap.appc.adapter.ssh.SshConnection; + +public class SshAdapterSshd implements SshAdapter { + + @Override + public SshConnection getConnection(String host, int port, String username, String password) { + return new SshConnectionSshd(host, port, username, password); + } +} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshConnectionSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshConnectionSshd.java new file mode 100644 index 000000000..c35c58798 --- /dev/null +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshConnectionSshd.java @@ -0,0 +1,236 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.ssh.sshd; + +import org.onap.appc.adapter.ssh.Constants; +import org.onap.appc.adapter.ssh.SshConnection; +import org.onap.appc.adapter.ssh.SshException; +import org.onap.appc.encryption.EncryptionTool; +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; +import org.apache.sshd.ClientChannel; +import org.apache.sshd.ClientSession; +import org.apache.sshd.SshClient; +import org.apache.sshd.client.channel.ChannelExec; +import org.apache.sshd.client.future.AuthFuture; +import org.apache.sshd.client.future.OpenFuture; +import org.apache.sshd.common.KeyPairProvider; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.io.OutputStream; +import java.security.KeyPair; + +/** + * Implementation of SshConnection interface based on Apache MINA SSHD library. + */ +class SshConnectionSshd implements SshConnection { + + private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); + + private static final long AUTH_TIMEOUT = 60000; + private static final long EXEC_TIMEOUT = 120000; + + private String host; + private int port; + private String username; + private String password; + private long timeout = EXEC_TIMEOUT; + private String keyFile; + private SshClient sshClient; + private ClientSession clientSession; + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { + this.host = host; + this.port = port; + this.username = username; + this.password = password; + this.keyFile = keyFile; + } + + public SshConnectionSshd(String host, int port, String username, String password) { + this(host, port, username, password, null); + } + + public SshConnectionSshd(String host, int port, String keyFile) { + this(host, port, null, null, keyFile); + } + + @Override + public void connect() { + sshClient = SshClient.setUpDefaultClient(); + sshClient.start(); + try { + clientSession = + sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); + if (password != null) { + clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); + } + if (keyFile != null) { + KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] { + keyFile + }); + KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); + clientSession.addPublicKeyIdentity(keyPair); + } + AuthFuture authFuture = clientSession.auth(); + authFuture.await(AUTH_TIMEOUT); + if (!authFuture.isSuccess()) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + + "]. Authentication failed."); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", + e); + } + if (logger.isDebugEnabled()) { + logger.debug("SSH: connected to [" + toString() + "]"); + } + } + + @Override + public void connectWithRetry() { + int retryCount = 0; + int retryDelay = 0; + int retriesLeft = 0; + retryCount = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_COUNT, + Constants.DEFAULT_CONNECTION_RETRY_COUNT); + retryDelay = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_DELAY, + Constants.DEFAULT_CONNECTION_RETRY_DELAY); + retriesLeft = retryCount + 1; + do { + try { + this.connect(); + break; + } catch (RuntimeException e) { + if (retriesLeft > 1) { + logger.debug("SSH Connection failed. Waiting for change in server's state."); + waitForConnection(retryDelay); + retriesLeft--; + logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1) + + "] out of [" + retryCount + "]"); + } else { + throw e; + } + } catch (Exception e) { + throw e; + } + } while (retriesLeft > 0); + } + + @Override + public void disconnect() { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: disconnecting from [" + toString() + "]"); + } + clientSession.close(false); + } finally { + if (sshClient != null) { + sshClient.stop(); + } + } + } + + @Override + public void setExecTimeout(long timeout) { + this.timeout = timeout; + } + + @Override + public int execCommand(String cmd, OutputStream out, OutputStream err) { + return execCommand(cmd, out, err, false); + } + + @Override + public int execCommandWithPty(String cmd, OutputStream out) { + return execCommand(cmd, out, out, true); + } + + private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: executing command"); + } + ChannelExec client = clientSession.createExecChannel(cmd); + client.setUsePty(usePty); // use pseudo-tty? + client.setOut(out); + client.setErr(err); + OpenFuture openFuture = client.open(); + int exitStatus = 0; + try { + client.waitFor(ClientChannel.CLOSED, timeout); + openFuture.verify(); + Integer exitStatusI = client.getExitStatus(); + if (exitStatusI == null) { + throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + + ":" + port + "]. Operation timed out."); + } + exitStatus = exitStatusI; + } finally { + client.close(false); + } + return exitStatus; + } catch (RuntimeException e) { + throw e; + } catch (Exception t) { + throw new SshException( + "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); + } + } + + private void waitForConnection(int retryDelay) { + long time = retryDelay * 1000L; + long future = System.currentTimeMillis() + time; + if (time != 0) { + while (System.currentTimeMillis() < future && time > 0) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + /* + * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that + * case, the thread is resumed before the delay time has actually expired, so re-calculate the + * amount of delay time needed and reenter the sleep until we get to the future time. + */ + time = future - System.currentTimeMillis(); + } + } + } + } + + @Override + public String toString() { + String address = host; + if (username != null) { + address = username + '@' + address; + } + return address; + } +} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshdDataAccessService.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshdDataAccessService.java new file mode 100644 index 000000000..07a814083 --- /dev/null +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/onap/appc/adapter/ssh/sshd/SshdDataAccessService.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.ssh.sshd; + +import javax.sql.rowset.CachedRowSet; + +import org.onap.appc.adapter.ssh.Constants; +import org.onap.appc.adapter.ssh.SshConnectionDetails; +import org.onap.appc.adapter.ssh.SshDataAccessException; +import org.onap.appc.adapter.ssh.SshDataAccessService; +import org.onap.ccsdk.sli.core.dblib.DbLibService; + +import java.sql.SQLException; +import java.util.ArrayList; + +public class SshdDataAccessService implements SshDataAccessService { + + private String schema = Constants.NETCONF_SCHEMA; + private DbLibService dbLibService; + + @Override + public void setSchema(String schema) { + this.schema = schema; + } + + @Override + public void setDbLibService(DbLibService dbLibService) { + this.dbLibService = dbLibService; + } + + @Override + public boolean retrieveConnectionDetails(String vnfType, SshConnectionDetails connectionDetails) throws SshDataAccessException { + + boolean recordFound = false; + + String queryString = "select " + Constants.USER_NAME_TABLE_FIELD_NAME + "," + Constants.PASSWORD_TABLE_FIELD_NAME + "," + Constants.PORT_NUMBER_TABLE_FIELD_NAME + " " + + "from " + Constants.DEVICE_AUTHENTICATION_TABLE_NAME + " " + + "where " + Constants.VNF_TYPE_TABLE_FIELD_NAME + " = ?"; + + ArrayList argList = new ArrayList<>(); + argList.add(vnfType); + + try { + + final CachedRowSet data = dbLibService.getData(queryString, argList, schema); + if (data.first()) { + recordFound = true; + connectionDetails.setUsername(data.getString(Constants.USER_NAME_TABLE_FIELD_NAME)); + connectionDetails.setPassword(data.getString(Constants.PASSWORD_TABLE_FIELD_NAME)); + connectionDetails.setPort(data.getInt(Constants.PORT_NUMBER_TABLE_FIELD_NAME)); + } + + } catch (SQLException e) { + throw new SshDataAccessException(e); + } + + return recordFound; + } + + @Override + public String retrieveConfigFileName(String xmlID) throws SshDataAccessException { + String fileContent; + + String queryString = "select " + Constants.FILE_CONTENT_TABLE_FIELD_NAME + " " + + "from " + Constants.CONFIGFILES_TABLE_NAME + " " + + "where " + Constants.FILE_NAME_TABLE_FIELD_NAME + " = ?"; + + ArrayList argList = new ArrayList<>(); + argList.add(xmlID); + + try { + + final CachedRowSet data = dbLibService.getData(queryString, argList, schema); + fileContent = data.getString(Constants.FILE_CONTENT_TABLE_FIELD_NAME); + + } catch (SQLException e) { + throw new SshDataAccessException(e); + } + + return fileContent; + } + + +} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSshd.java deleted file mode 100644 index a5bbe34e2..000000000 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSshd.java +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.ssh.sshd; - -import org.onap.appc.adapter.ssh.SshAdapter; -import org.onap.appc.adapter.ssh.SshConnection; - -public class SshAdapterSshd implements SshAdapter { - - @Override - public SshConnection getConnection(String host, int port, String username, String password) { - return new SshConnectionSshd(host, port, username, password); - } -} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java deleted file mode 100644 index c35c58798..000000000 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java +++ /dev/null @@ -1,236 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.ssh.sshd; - -import org.onap.appc.adapter.ssh.Constants; -import org.onap.appc.adapter.ssh.SshConnection; -import org.onap.appc.adapter.ssh.SshException; -import org.onap.appc.encryption.EncryptionTool; -import org.onap.appc.configuration.Configuration; -import org.onap.appc.configuration.ConfigurationFactory; -import org.apache.sshd.ClientChannel; -import org.apache.sshd.ClientSession; -import org.apache.sshd.SshClient; -import org.apache.sshd.client.channel.ChannelExec; -import org.apache.sshd.client.future.AuthFuture; -import org.apache.sshd.client.future.OpenFuture; -import org.apache.sshd.common.KeyPairProvider; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.OutputStream; -import java.security.KeyPair; - -/** - * Implementation of SshConnection interface based on Apache MINA SSHD library. - */ -class SshConnectionSshd implements SshConnection { - - private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); - - private static final long AUTH_TIMEOUT = 60000; - private static final long EXEC_TIMEOUT = 120000; - - private String host; - private int port; - private String username; - private String password; - private long timeout = EXEC_TIMEOUT; - private String keyFile; - private SshClient sshClient; - private ClientSession clientSession; - private static final Configuration configuration = ConfigurationFactory.getConfiguration(); - - public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { - this.host = host; - this.port = port; - this.username = username; - this.password = password; - this.keyFile = keyFile; - } - - public SshConnectionSshd(String host, int port, String username, String password) { - this(host, port, username, password, null); - } - - public SshConnectionSshd(String host, int port, String keyFile) { - this(host, port, null, null, keyFile); - } - - @Override - public void connect() { - sshClient = SshClient.setUpDefaultClient(); - sshClient.start(); - try { - clientSession = - sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); - if (password != null) { - clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); - } - if (keyFile != null) { - KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] { - keyFile - }); - KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); - clientSession.addPublicKeyIdentity(keyPair); - } - AuthFuture authFuture = clientSession.auth(); - authFuture.await(AUTH_TIMEOUT); - if (!authFuture.isSuccess()) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port - + "]. Authentication failed."); - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", - e); - } - if (logger.isDebugEnabled()) { - logger.debug("SSH: connected to [" + toString() + "]"); - } - } - - @Override - public void connectWithRetry() { - int retryCount = 0; - int retryDelay = 0; - int retriesLeft = 0; - retryCount = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_COUNT, - Constants.DEFAULT_CONNECTION_RETRY_COUNT); - retryDelay = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_DELAY, - Constants.DEFAULT_CONNECTION_RETRY_DELAY); - retriesLeft = retryCount + 1; - do { - try { - this.connect(); - break; - } catch (RuntimeException e) { - if (retriesLeft > 1) { - logger.debug("SSH Connection failed. Waiting for change in server's state."); - waitForConnection(retryDelay); - retriesLeft--; - logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1) - + "] out of [" + retryCount + "]"); - } else { - throw e; - } - } catch (Exception e) { - throw e; - } - } while (retriesLeft > 0); - } - - @Override - public void disconnect() { - try { - if (logger.isDebugEnabled()) { - logger.debug("SSH: disconnecting from [" + toString() + "]"); - } - clientSession.close(false); - } finally { - if (sshClient != null) { - sshClient.stop(); - } - } - } - - @Override - public void setExecTimeout(long timeout) { - this.timeout = timeout; - } - - @Override - public int execCommand(String cmd, OutputStream out, OutputStream err) { - return execCommand(cmd, out, err, false); - } - - @Override - public int execCommandWithPty(String cmd, OutputStream out) { - return execCommand(cmd, out, out, true); - } - - private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { - try { - if (logger.isDebugEnabled()) { - logger.debug("SSH: executing command"); - } - ChannelExec client = clientSession.createExecChannel(cmd); - client.setUsePty(usePty); // use pseudo-tty? - client.setOut(out); - client.setErr(err); - OpenFuture openFuture = client.open(); - int exitStatus = 0; - try { - client.waitFor(ClientChannel.CLOSED, timeout); - openFuture.verify(); - Integer exitStatusI = client.getExitStatus(); - if (exitStatusI == null) { - throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host - + ":" + port + "]. Operation timed out."); - } - exitStatus = exitStatusI; - } finally { - client.close(false); - } - return exitStatus; - } catch (RuntimeException e) { - throw e; - } catch (Exception t) { - throw new SshException( - "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); - } - } - - private void waitForConnection(int retryDelay) { - long time = retryDelay * 1000L; - long future = System.currentTimeMillis() + time; - if (time != 0) { - while (System.currentTimeMillis() < future && time > 0) { - try { - Thread.sleep(time); - } catch (InterruptedException e) { - /* - * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that - * case, the thread is resumed before the delay time has actually expired, so re-calculate the - * amount of delay time needed and reenter the sleep until we get to the future time. - */ - time = future - System.currentTimeMillis(); - } - } - } - } - - @Override - public String toString() { - String address = host; - if (username != null) { - address = username + '@' + address; - } - return address; - } -} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java deleted file mode 100644 index 07a814083..000000000 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java +++ /dev/null @@ -1,106 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.ssh.sshd; - -import javax.sql.rowset.CachedRowSet; - -import org.onap.appc.adapter.ssh.Constants; -import org.onap.appc.adapter.ssh.SshConnectionDetails; -import org.onap.appc.adapter.ssh.SshDataAccessException; -import org.onap.appc.adapter.ssh.SshDataAccessService; -import org.onap.ccsdk.sli.core.dblib.DbLibService; - -import java.sql.SQLException; -import java.util.ArrayList; - -public class SshdDataAccessService implements SshDataAccessService { - - private String schema = Constants.NETCONF_SCHEMA; - private DbLibService dbLibService; - - @Override - public void setSchema(String schema) { - this.schema = schema; - } - - @Override - public void setDbLibService(DbLibService dbLibService) { - this.dbLibService = dbLibService; - } - - @Override - public boolean retrieveConnectionDetails(String vnfType, SshConnectionDetails connectionDetails) throws SshDataAccessException { - - boolean recordFound = false; - - String queryString = "select " + Constants.USER_NAME_TABLE_FIELD_NAME + "," + Constants.PASSWORD_TABLE_FIELD_NAME + "," + Constants.PORT_NUMBER_TABLE_FIELD_NAME + " " + - "from " + Constants.DEVICE_AUTHENTICATION_TABLE_NAME + " " + - "where " + Constants.VNF_TYPE_TABLE_FIELD_NAME + " = ?"; - - ArrayList argList = new ArrayList<>(); - argList.add(vnfType); - - try { - - final CachedRowSet data = dbLibService.getData(queryString, argList, schema); - if (data.first()) { - recordFound = true; - connectionDetails.setUsername(data.getString(Constants.USER_NAME_TABLE_FIELD_NAME)); - connectionDetails.setPassword(data.getString(Constants.PASSWORD_TABLE_FIELD_NAME)); - connectionDetails.setPort(data.getInt(Constants.PORT_NUMBER_TABLE_FIELD_NAME)); - } - - } catch (SQLException e) { - throw new SshDataAccessException(e); - } - - return recordFound; - } - - @Override - public String retrieveConfigFileName(String xmlID) throws SshDataAccessException { - String fileContent; - - String queryString = "select " + Constants.FILE_CONTENT_TABLE_FIELD_NAME + " " + - "from " + Constants.CONFIGFILES_TABLE_NAME + " " + - "where " + Constants.FILE_NAME_TABLE_FIELD_NAME + " = ?"; - - ArrayList argList = new ArrayList<>(); - argList.add(xmlID); - - try { - - final CachedRowSet data = dbLibService.getData(queryString, argList, schema); - fileContent = data.getString(Constants.FILE_CONTENT_TABLE_FIELD_NAME); - - } catch (SQLException e) { - throw new SshDataAccessException(e); - } - - return fileContent; - } - - -} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSample.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSample.java new file mode 100644 index 000000000..f79a81856 --- /dev/null +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterSample.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.ssh.sshd; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import org.onap.appc.adapter.ssh.SshAdapter; +import org.onap.appc.adapter.ssh.SshConnection; +import org.onap.appc.adapter.ssh.sshd.SshAdapterSshd; + +public class SshAdapterSample { + + public static void main(String[] args) { + String host = "hostname"; + int port = 22; + String username = "user"; + String password = "secret"; + String command = "ls"; + + SshAdapter sshAdapter = new SshAdapterSshd(); + SshConnection sshConnection = sshAdapter.getConnection(host, port, username, password); + sshConnection.connect(); + try { + OutputStream stdout = new ByteArrayOutputStream(); + OutputStream stderr = new ByteArrayOutputStream(); + int status = sshConnection.execCommand(command, stdout, stderr); + if(status == 0) { + System.out.println("Command executed successfully. Output:\n" + stdout.toString()); + } else { + System.err.println("Command returned status " + status + ". Error:\n" + stderr.toString()); + } + } finally { + sshConnection.disconnect(); + } + } +} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterTest.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterTest.java new file mode 100644 index 000000000..12b2258d0 --- /dev/null +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/onap/appc/adapter/ssh/sshd/SshAdapterTest.java @@ -0,0 +1,250 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.ssh.sshd; + +import org.apache.sshd.SshServer; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.util.OsUtils; +import org.apache.sshd.server.Command; +import org.apache.sshd.server.CommandFactory; +import org.apache.sshd.server.PasswordAuthenticator; +import org.apache.sshd.server.PublickeyAuthenticator; +import org.apache.sshd.server.command.ScpCommandFactory; +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; +import org.apache.sshd.server.session.ServerSession; +import org.apache.sshd.server.sftp.SftpSubsystem; +import org.apache.sshd.server.shell.ProcessShellFactory; +import org.hamcrest.CoreMatchers; +import org.junit.*; +import org.junit.rules.ExpectedException; +import org.onap.appc.adapter.ssh.SshAdapter; +import org.onap.appc.adapter.ssh.SshConnection; +import org.onap.appc.adapter.ssh.SshException; +import org.onap.appc.adapter.ssh.sshd.SshAdapterSshd; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.BindException; +import java.security.PublicKey; +import java.util.Collections; +import java.util.EnumSet; + +public class SshAdapterTest { + + private static final boolean START_SERVER = true; + private static final String SSH_HOST = "localhost"; + private static final int SSH_PORT = 2222; + private static final String SSH_USERNAME = "test"; + private static final String SSH_PASSWORD = "test"; + private static final String F_TEST_CMD = "ping -%c 4 %s"; + + private int sshPort = SSH_PORT; + private SshServer sshd; + private SshAdapter sshAdapter = new SshAdapterSshd(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testExecute() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); + SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); + try { + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, stderr, false); + Assert.assertEquals(stdout.toString() + ". " + stderr.toString(), 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testExecuteWithPty() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); + SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); + try { + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, null, true); + Assert.assertEquals(stdout.toString() + ". " + stdout.toString(), 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testExecuteInvalidCommand() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "nosuchhost"); + SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); + try { + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, stderr, false); + Assert.assertNotEquals(stdout.toString() + ". " + stderr.toString(), 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testWrongUsername() { + thrown.expect(SshException.class); + thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); + disconnect(connect("WrongUsername", SSH_PASSWORD)); + } + + @Test + public void testWrongPassword() { + thrown.expect(SshException.class); + thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); + disconnect(connect(SSH_USERNAME, "WrongPassword")); + } + + @Before + public void beforeTest() throws IOException { + if (START_SERVER) { + startServer(); + } + } + + @After + public void afterTest() throws InterruptedException { + stopServer(); + } + + private SshConnection connect(String username, String password) { + SshConnection sshConnection = sshAdapter.getConnection(SSH_HOST, sshPort, username, password); + sshConnection.connect(); + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + return sshConnection; + } + + private void disconnect(SshConnection sshConnection) { + sshConnection.disconnect(); + System.out.println("SSH client disconnected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + + private int execCmd(SshConnection sshConnection, String cmd, OutputStream stdout, OutputStream stderr, boolean usePty) { + System.out.println("=> Running command [" + cmd + "] over SSH"); + int status; + if (usePty) { + status = sshConnection.execCommandWithPty(cmd, stdout); + } else { + status = sshConnection.execCommand(cmd, stdout, stderr); + } + System.out.println("=> Command [" + cmd + "] status is [" + status + "], stdout is [" + String.valueOf(stdout) + "], stderr is [" + String.valueOf(stderr) + "]"); + return status; + } + + private void startServer() throws IOException { + sshd = SshServer.setUpDefaultServer(); + sshd.setSubsystemFactories(Collections.>singletonList(new SftpSubsystem.Factory())); + sshd.setCommandFactory(new ScpCommandFactory(new CommandFactory() { + + public Command createCommand(String command) { + EnumSet ttyOptions; + if (OsUtils.isUNIX()) { + ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr); + } else { + ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr); + } + return new ProcessShellFactory(command.split(" "), ttyOptions).create(); + } + })); + if (OsUtils.isUNIX()) { + sshd.setShellFactory(new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"}, + EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr))); + } else { + sshd.setShellFactory(new ProcessShellFactory(new String[]{"cmd.exe "}, + EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr))); + } +// if(SecurityUtils.isBouncyCastleRegistered()) { +// sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.pem")); +// } else { + sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.ser")); +// } + sshd.setPasswordAuthenticator(new PasswordAuthenticator() { + + @Override + public boolean authenticate(String username, String password, ServerSession session) { + return (SSH_USERNAME.equals(username) && SSH_PASSWORD.equals(password)); + } + }); + sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { + + public boolean authenticate(String username, PublicKey key, ServerSession session) { + return true; + } + }); + sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n"); + startServer0(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + } + + private void startServer0() throws IOException { + boolean serverStarted = false; + IOException exception = null; + while (!serverStarted && (sshPort < Integer.MAX_VALUE)) { + try { + System.out.println("Starting SSH server on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + sshd.setPort(sshPort); + sshd.start(); + serverStarted = true; + } catch (BindException e) { + System.err.println("Cannot start SSH server on port [" + sshPort + "]. " + e.getMessage()); + if (exception == null) { + // store first thrown exception - will be thrown if cannot start the server + exception = e; + } + sshPort++; + } + } + if (!serverStarted) { + throw exception; + } + System.out.println("SSH server started on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + + private void stopServer() { + try { + if (sshd != null) { + sshd.stop(true); + System.out.println("SSH server stopped on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + } catch (InterruptedException e) { + System.err.println("=> Error stopping SSH server."); + e.printStackTrace(); + } finally { + sshd = null; + } + } +} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSample.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSample.java deleted file mode 100644 index f79a81856..000000000 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterSample.java +++ /dev/null @@ -1,59 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.ssh.sshd; - -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; - -import org.onap.appc.adapter.ssh.SshAdapter; -import org.onap.appc.adapter.ssh.SshConnection; -import org.onap.appc.adapter.ssh.sshd.SshAdapterSshd; - -public class SshAdapterSample { - - public static void main(String[] args) { - String host = "hostname"; - int port = 22; - String username = "user"; - String password = "secret"; - String command = "ls"; - - SshAdapter sshAdapter = new SshAdapterSshd(); - SshConnection sshConnection = sshAdapter.getConnection(host, port, username, password); - sshConnection.connect(); - try { - OutputStream stdout = new ByteArrayOutputStream(); - OutputStream stderr = new ByteArrayOutputStream(); - int status = sshConnection.execCommand(command, stdout, stderr); - if(status == 0) { - System.out.println("Command executed successfully. Output:\n" + stdout.toString()); - } else { - System.err.println("Command returned status " + status + ". Error:\n" + stderr.toString()); - } - } finally { - sshConnection.disconnect(); - } - } -} diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java deleted file mode 100644 index 12b2258d0..000000000 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java +++ /dev/null @@ -1,250 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.ssh.sshd; - -import org.apache.sshd.SshServer; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.util.OsUtils; -import org.apache.sshd.server.Command; -import org.apache.sshd.server.CommandFactory; -import org.apache.sshd.server.PasswordAuthenticator; -import org.apache.sshd.server.PublickeyAuthenticator; -import org.apache.sshd.server.command.ScpCommandFactory; -import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import org.apache.sshd.server.session.ServerSession; -import org.apache.sshd.server.sftp.SftpSubsystem; -import org.apache.sshd.server.shell.ProcessShellFactory; -import org.hamcrest.CoreMatchers; -import org.junit.*; -import org.junit.rules.ExpectedException; -import org.onap.appc.adapter.ssh.SshAdapter; -import org.onap.appc.adapter.ssh.SshConnection; -import org.onap.appc.adapter.ssh.SshException; -import org.onap.appc.adapter.ssh.sshd.SshAdapterSshd; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.BindException; -import java.security.PublicKey; -import java.util.Collections; -import java.util.EnumSet; - -public class SshAdapterTest { - - private static final boolean START_SERVER = true; - private static final String SSH_HOST = "localhost"; - private static final int SSH_PORT = 2222; - private static final String SSH_USERNAME = "test"; - private static final String SSH_PASSWORD = "test"; - private static final String F_TEST_CMD = "ping -%c 4 %s"; - - private int sshPort = SSH_PORT; - private SshServer sshd; - private SshAdapter sshAdapter = new SshAdapterSshd(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void testExecute() { - String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); - SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); - try { - System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - ByteArrayOutputStream stdout = new ByteArrayOutputStream(); - ByteArrayOutputStream stderr = new ByteArrayOutputStream(); - int status = execCmd(sshConnection, cmd, stdout, stderr, false); - Assert.assertEquals(stdout.toString() + ". " + stderr.toString(), 0, status); - } finally { - disconnect(sshConnection); - } - } - - @Test - public void testExecuteWithPty() { - String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); - SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); - try { - System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - ByteArrayOutputStream stdout = new ByteArrayOutputStream(); - int status = execCmd(sshConnection, cmd, stdout, null, true); - Assert.assertEquals(stdout.toString() + ". " + stdout.toString(), 0, status); - } finally { - disconnect(sshConnection); - } - } - - @Test - public void testExecuteInvalidCommand() { - String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "nosuchhost"); - SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD); - try { - ByteArrayOutputStream stdout = new ByteArrayOutputStream(); - ByteArrayOutputStream stderr = new ByteArrayOutputStream(); - int status = execCmd(sshConnection, cmd, stdout, stderr, false); - Assert.assertNotEquals(stdout.toString() + ". " + stderr.toString(), 0, status); - } finally { - disconnect(sshConnection); - } - } - - @Test - public void testWrongUsername() { - thrown.expect(SshException.class); - thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); - disconnect(connect("WrongUsername", SSH_PASSWORD)); - } - - @Test - public void testWrongPassword() { - thrown.expect(SshException.class); - thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); - disconnect(connect(SSH_USERNAME, "WrongPassword")); - } - - @Before - public void beforeTest() throws IOException { - if (START_SERVER) { - startServer(); - } - } - - @After - public void afterTest() throws InterruptedException { - stopServer(); - } - - private SshConnection connect(String username, String password) { - SshConnection sshConnection = sshAdapter.getConnection(SSH_HOST, sshPort, username, password); - sshConnection.connect(); - System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - return sshConnection; - } - - private void disconnect(SshConnection sshConnection) { - sshConnection.disconnect(); - System.out.println("SSH client disconnected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - } - - private int execCmd(SshConnection sshConnection, String cmd, OutputStream stdout, OutputStream stderr, boolean usePty) { - System.out.println("=> Running command [" + cmd + "] over SSH"); - int status; - if (usePty) { - status = sshConnection.execCommandWithPty(cmd, stdout); - } else { - status = sshConnection.execCommand(cmd, stdout, stderr); - } - System.out.println("=> Command [" + cmd + "] status is [" + status + "], stdout is [" + String.valueOf(stdout) + "], stderr is [" + String.valueOf(stderr) + "]"); - return status; - } - - private void startServer() throws IOException { - sshd = SshServer.setUpDefaultServer(); - sshd.setSubsystemFactories(Collections.>singletonList(new SftpSubsystem.Factory())); - sshd.setCommandFactory(new ScpCommandFactory(new CommandFactory() { - - public Command createCommand(String command) { - EnumSet ttyOptions; - if (OsUtils.isUNIX()) { - ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr); - } else { - ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr); - } - return new ProcessShellFactory(command.split(" "), ttyOptions).create(); - } - })); - if (OsUtils.isUNIX()) { - sshd.setShellFactory(new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"}, - EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr))); - } else { - sshd.setShellFactory(new ProcessShellFactory(new String[]{"cmd.exe "}, - EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr))); - } -// if(SecurityUtils.isBouncyCastleRegistered()) { -// sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.pem")); -// } else { - sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.ser")); -// } - sshd.setPasswordAuthenticator(new PasswordAuthenticator() { - - @Override - public boolean authenticate(String username, String password, ServerSession session) { - return (SSH_USERNAME.equals(username) && SSH_PASSWORD.equals(password)); - } - }); - sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() { - - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return true; - } - }); - sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n"); - startServer0(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // ignore - } - } - - private void startServer0() throws IOException { - boolean serverStarted = false; - IOException exception = null; - while (!serverStarted && (sshPort < Integer.MAX_VALUE)) { - try { - System.out.println("Starting SSH server on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - sshd.setPort(sshPort); - sshd.start(); - serverStarted = true; - } catch (BindException e) { - System.err.println("Cannot start SSH server on port [" + sshPort + "]. " + e.getMessage()); - if (exception == null) { - // store first thrown exception - will be thrown if cannot start the server - exception = e; - } - sshPort++; - } - } - if (!serverStarted) { - throw exception; - } - System.out.println("SSH server started on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - } - - private void stopServer() { - try { - if (sshd != null) { - sshd.stop(true); - System.out.println("SSH server stopped on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); - } - } catch (InterruptedException e) { - System.err.println("=> Error stopping SSH server."); - e.printStackTrace(); - } finally { - sshd = null; - } - } -} -- cgit 1.2.3-korg