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