Updating licenses in all files
[appc.git] / appc-adapters / appc-ssh-adapter / appc-ssh-adapter-sshd / src / test / java / org / openecomp / appc / adapter / ssh / sshd / SshAdapterTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Amdocs
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
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
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=========================================================
20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22
23 package org.openecomp.appc.adapter.ssh.sshd;
24
25 import org.apache.sshd.SshServer;
26 import org.apache.sshd.common.NamedFactory;
27 import org.apache.sshd.common.util.OsUtils;
28 import org.apache.sshd.server.Command;
29 import org.apache.sshd.server.CommandFactory;
30 import org.apache.sshd.server.PasswordAuthenticator;
31 import org.apache.sshd.server.PublickeyAuthenticator;
32 import org.apache.sshd.server.command.ScpCommandFactory;
33 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
34 import org.apache.sshd.server.session.ServerSession;
35 import org.apache.sshd.server.sftp.SftpSubsystem;
36 import org.apache.sshd.server.shell.ProcessShellFactory;
37 import org.hamcrest.CoreMatchers;
38 import org.junit.*;
39 import org.junit.rules.ExpectedException;
40 import org.openecomp.appc.adapter.ssh.SshAdapter;
41 import org.openecomp.appc.adapter.ssh.SshConnection;
42 import org.openecomp.appc.adapter.ssh.SshException;
43 import org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd;
44
45 import java.io.ByteArrayOutputStream;
46 import java.io.IOException;
47 import java.io.OutputStream;
48 import java.net.BindException;
49 import java.security.PublicKey;
50 import java.util.Collections;
51 import java.util.EnumSet;
52
53 public class SshAdapterTest {
54
55     private static final boolean START_SERVER = true;
56     private static final String SSH_HOST = "localhost";
57     private static final int SSH_PORT = 2222;
58     private static final String SSH_USERNAME = "test";
59     private static final String SSH_PASSWORD = "test";
60     private static final String F_TEST_CMD = "ping -%c 4 %s";
61
62     private int sshPort = SSH_PORT;
63     private SshServer sshd;
64     private SshAdapter sshAdapter = new SshAdapterSshd();
65
66     @Rule
67     public ExpectedException thrown = ExpectedException.none();
68
69     @Test
70     public void testExecute() {
71         String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost");
72         SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
73         try {
74             System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
75             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
76             ByteArrayOutputStream stderr = new ByteArrayOutputStream();
77             int status = execCmd(sshConnection, cmd, stdout, stderr, false);
78             Assert.assertEquals(stdout.toString() + ". " + stderr.toString(), 0, status);
79         } finally {
80             disconnect(sshConnection);
81         }
82     }
83
84     @Test
85     public void testExecuteWithPty() {
86         String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost");
87         SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
88         try {
89             System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
90             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
91             int status = execCmd(sshConnection, cmd, stdout, null, true);
92             Assert.assertEquals(stdout.toString() + ". " + stdout.toString(), 0, status);
93         } finally {
94             disconnect(sshConnection);
95         }
96     }
97
98     @Test
99     public void testExecuteInvalidCommand() {
100         String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "nosuchhost");
101         SshConnection sshConnection = connect(SSH_USERNAME, SSH_PASSWORD);
102         try {
103             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
104             ByteArrayOutputStream stderr = new ByteArrayOutputStream();
105             int status = execCmd(sshConnection, cmd, stdout, stderr, false);
106             Assert.assertNotEquals(stdout.toString() + ". " + stderr.toString(), 0, status);
107         } finally {
108             disconnect(sshConnection);
109         }
110     }
111
112     @Test
113     public void testWrongUsername() {
114         thrown.expect(SshException.class);
115         thrown.expectMessage(CoreMatchers.containsString("Authentication failed"));
116         disconnect(connect("WrongUsername", SSH_PASSWORD));
117     }
118
119     @Test
120     public void testWrongPassword() {
121         thrown.expect(SshException.class);
122         thrown.expectMessage(CoreMatchers.containsString("Authentication failed"));
123         disconnect(connect(SSH_USERNAME, "WrongPassword"));
124     }
125
126     @Before
127     public void beforeTest() throws IOException {
128         if (START_SERVER) {
129             startServer();
130         }
131     }
132
133     @After
134     public void afterTest() throws InterruptedException {
135         stopServer();
136     }
137
138     private SshConnection connect(String username, String password) {
139         SshConnection sshConnection = sshAdapter.getConnection(SSH_HOST, sshPort, username, password);
140         sshConnection.connect();
141         System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
142         return sshConnection;
143     }
144
145     private void disconnect(SshConnection sshConnection) {
146         sshConnection.disconnect();
147         System.out.println("SSH client disconnected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
148     }
149
150     private int execCmd(SshConnection sshConnection, String cmd, OutputStream stdout, OutputStream stderr, boolean usePty) {
151         System.out.println("=> Running command [" + cmd + "] over SSH");
152         int status;
153         if (usePty) {
154             status = sshConnection.execCommandWithPty(cmd, stdout);
155         } else {
156             status = sshConnection.execCommand(cmd, stdout, stderr);
157         }
158         System.out.println("=> Command [" + cmd + "] status is [" + status + "], stdout is [" + String.valueOf(stdout) + "], stderr is [" + String.valueOf(stderr) + "]");
159         return status;
160     }
161
162     private void startServer() throws IOException {
163         sshd = SshServer.setUpDefaultServer();
164         sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
165         sshd.setCommandFactory(new ScpCommandFactory(new CommandFactory() {
166
167             public Command createCommand(String command) {
168                 EnumSet<ProcessShellFactory.TtyOptions> ttyOptions;
169                 if (OsUtils.isUNIX()) {
170                     ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr);
171                 } else {
172                     ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr);
173                 }
174                 return new ProcessShellFactory(command.split(" "), ttyOptions).create();
175             }
176         }));
177         if (OsUtils.isUNIX()) {
178             sshd.setShellFactory(new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"},
179                     EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr)));
180         } else {
181             sshd.setShellFactory(new ProcessShellFactory(new String[]{"cmd.exe "},
182                     EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr)));
183         }
184 //              if(SecurityUtils.isBouncyCastleRegistered()) {
185 //                      sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.pem"));
186 //              } else {
187         sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System.getProperty("java.io.tmpdir") + "/key.ser"));
188 //              }
189         sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
190
191             @Override
192             public boolean authenticate(String username, String password, ServerSession session) {
193                 return (SSH_USERNAME.equals(username) && SSH_PASSWORD.equals(password));
194             }
195         });
196         sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
197
198             public boolean authenticate(String username, PublicKey key, ServerSession session) {
199                 return true;
200             }
201         });
202         sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n");
203         startServer0();
204         try {
205             Thread.sleep(1000);
206         } catch (InterruptedException e) {
207             // ignore
208         }
209     }
210
211     private void startServer0() throws IOException {
212         boolean serverStarted = false;
213         IOException exception = null;
214         while (!serverStarted && (sshPort < Integer.MAX_VALUE)) {
215             try {
216                 System.out.println("Starting SSH server on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
217                 sshd.setPort(sshPort);
218                 sshd.start();
219                 serverStarted = true;
220             } catch (BindException e) {
221                 System.err.println("Cannot start SSH server on port [" + sshPort + "]. " + e.getMessage());
222                 if (exception == null) {
223                     // store first thrown exception - will be thrown if cannot start the server
224                     exception = e;
225                 }
226                 sshPort++;
227             }
228         }
229         if (!serverStarted) {
230             throw exception;
231         }
232         System.out.println("SSH server started on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
233     }
234
235     private void stopServer() {
236         try {
237             if (sshd != null) {
238                 sshd.stop(true);
239                 System.out.println("SSH server stopped on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]");
240             }
241         } catch (InterruptedException e) {
242             System.err.println("=> Error stopping SSH server.");
243             e.printStackTrace();
244         } finally {
245             sshd = null;
246         }
247     }
248 }