2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.openecomp.appc.adapter.ssh.sshd;
24 import org.apache.sshd.SshServer;
25 import org.apache.sshd.common.NamedFactory;
26 import org.apache.sshd.common.util.OsUtils;
27 import org.apache.sshd.server.Command;
28 import org.apache.sshd.server.CommandFactory;
29 import org.apache.sshd.server.PasswordAuthenticator;
30 import org.apache.sshd.server.PublickeyAuthenticator;
31 import org.apache.sshd.server.command.ScpCommandFactory;
32 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
33 import org.apache.sshd.server.session.ServerSession;
34 import org.apache.sshd.server.sftp.SftpSubsystem;
35 import org.apache.sshd.server.shell.ProcessShellFactory;
36 import org.hamcrest.CoreMatchers;
38 import org.junit.rules.ExpectedException;
39 import org.openecomp.appc.adapter.ssh.SshAdapter;
40 import org.openecomp.appc.adapter.ssh.SshConnection;
41 import org.openecomp.appc.adapter.ssh.SshException;
42 import org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd;
44 import java.io.ByteArrayOutputStream;
45 import java.io.IOException;
46 import java.io.OutputStream;
47 import java.net.BindException;
48 import java.security.PublicKey;
49 import java.util.Collections;
50 import java.util.EnumSet;
52 public class SshAdapterTest {
54 private static final boolean START_SERVER = true;
55 private static final String SSH_HOST = "localhost";
56 private static final int SSH_PORT = 2222;
57 private static final String SSH_USERNAME = "test";
58 private static final String SSH_PASSWORD = "test";
59 private static final String F_TEST_CMD = "ping -%c 4 %s";
61 private int sshPort = SSH_PORT;
62 private SshServer sshd;
63 private SshAdapter sshAdapter = new SshAdapterSshd();
66 public ExpectedException thrown = ExpectedException.none();
69 public void testExecute() {
70 String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost");
71 SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
73 System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
74 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
75 ByteArrayOutputStream stderr = new ByteArrayOutputStream();
76 int status = execCmd(sshConnection, cmd, stdout, stderr, false);
77 Assert.assertEquals(stdout.toString() + ". " + stderr.toString(), 0, status);
79 disconnect(sshConnection);
84 public void testExecuteWithPty() {
85 String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost");
86 SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
88 System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
89 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
90 int status = execCmd(sshConnection, cmd, stdout, null, true);
91 Assert.assertEquals(stdout.toString() + ". " + stdout.toString(), 0, status);
93 disconnect(sshConnection);
98 public void testExecuteInvalidCommand() {
99 String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "nosuchhost");
100 SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
102 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
103 ByteArrayOutputStream stderr = new ByteArrayOutputStream();
104 int status = execCmd(sshConnection, cmd, stdout, stderr, false);
105 Assert.assertNotEquals(stdout.toString() + ". " + stderr.toString(), 0, status);
107 disconnect(sshConnection);
112 public void testWrongUsername() {
113 thrown.expect(SshException.class);
114 thrown.expectMessage(CoreMatchers.containsString("Authentication failed"));
115 disconnect(connect("WrongUsername", SSH_PASSWORD));
119 public void testWrongPassword() {
120 thrown.expect(SshException.class);
121 thrown.expectMessage(CoreMatchers.containsString("Authentication failed"));
122 disconnect(connect(SSH_USERNAME, "WrongPassword"));
126 public void beforeTest() throws IOException {
133 public void afterTest() throws InterruptedException {
137 private SshConnection connect(String username, String password) {
138 SshConnection sshConnection = sshAdapter.getConnection(SSH_HOST, sshPort, username, password);
139 sshConnection.connect();
140 System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
141 return sshConnection;
144 private void disconnect(SshConnection sshConnection) {
145 sshConnection.disconnect();
146 System.out.println("SSH client disconnected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
149 private int execCmd(SshConnection sshConnection, String cmd, OutputStream stdout, OutputStream stderr, boolean usePty) {
150 System.out.println("=> Running command [" + cmd + "] over SSH");
153 status = sshConnection.execCommandWithPty(cmd, stdout);
155 status = sshConnection.execCommand(cmd, stdout, stderr);
157 System.out.println("=> Command [" + cmd + "] status is [" + status + "], stdout is [" + String.valueOf(stdout) + "], stderr is [" + String.valueOf(stderr) + "]");
161 private void startServer() throws IOException {
162 sshd = SshServer.setUpDefaultServer();
163 sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
164 sshd.setCommandFactory(new ScpCommandFactory(new CommandFactory() {
166 public Command createCommand(String command) {
167 EnumSet<ProcessShellFactory.TtyOptions> ttyOptions;
168 if (OsUtils.isUNIX()) {
169 ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr);
171 ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr);
173 return new ProcessShellFactory(command.split(" "), ttyOptions).create();
176 if (OsUtils.isUNIX()) {
177 sshd.setShellFactory(new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"},
178 EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr)));
180 sshd.setShellFactory(new ProcessShellFactory(new String[]{"cmd.exe "},
181 EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr)));
183 // if(SecurityUtils.isBouncyCastleRegistered()) {
184 // sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.pem"));
186 sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.ser"));
188 sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
191 public boolean authenticate(String username, String password, ServerSession session) {
192 return (SSH_USERNAME.equals(username) && SSH_PASSWORD.equals(password));
195 sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
197 public boolean authenticate(String username, PublicKey key, ServerSession session) {
201 sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n");
205 } catch (InterruptedException e) {
210 private void startServer0() throws IOException {
211 boolean serverStarted = false;
212 IOException exception = null;
213 while (!serverStarted && (sshPort < Integer.MAX_VALUE)) {
215 System.out.println("Starting SSH server on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
216 sshd.setPort(sshPort);
218 serverStarted = true;
219 } catch (BindException e) {
220 System.err.println("Cannot start SSH server on port [" + sshPort + "]. " + e.getMessage());
221 if (exception == null) {
222 // store first thrown exception - will be thrown if cannot start the server
228 if (!serverStarted) {
231 System.out.println("SSH server started on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
234 private void stopServer() {
238 System.out.println("SSH server stopped on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
240 } catch (InterruptedException e) {
241 System.err.println("=> Error stopping SSH server.");