9f1799821d232672d2bc549bb7252f530f2d203a
[ccsdk/sli/adaptors.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK
4  * ================================================================================
5  * Copyright (C) 2018 Samsung Electronics. All rights reserved.
6  * ================================================================================
7  *
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  *
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
30 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
31 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
32
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35
36 /**
37  * Returns a custom SSH client
38  * - based on options
39  * - can create one with ssl using an X509 certificate that does NOT have a known CA
40  * - create one which trusts ALL SSL certificates
41  * - return default sshclient (which only trusts known CAs from default cacerts file for process) this is the default
42  * option
43  **/
44 public class ConnectionBuilder {
45
46     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
47     SshConnection sshConnection;
48
49     /**
50      * Constructor that initializes an ssh client based on username and password
51      **/
52     public ConnectionBuilder(String host, String port, String userName, String userPasswd) {
53         sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd);
54     }
55
56     /**
57      * Constructor that initializes an ssh client based on ssh certificate
58      * This is still not supported in 1.3.0 version
59      **/
60     public ConnectionBuilder(String host, String port, String certFile) {
61         sshConnection = new SshConnection(host, Integer.parseInt(port), certFile);
62     }
63
64
65     /**
66      * 1. Connect to SSH server.
67      * 2. Exec remote command over SSH. Return command execution status.
68      * Command output is written to out or err stream.
69      *
70      * @param cmd Commands to execute
71      * @return command execution status
72      */
73     public SaltstackResult connectNExecute(String cmd, long execTimeout) throws IOException {
74         return connectNExecute(cmd, false, execTimeout);
75     }
76
77     /**
78      * 1. Connect to SSH server with retry enabled.
79      * 2. Exec remote command over SSH. Return command execution status.
80      * Command output is written to out or err stream.
81      *
82      * @param cmd       Commands to execute
83      * @param withRetry make a SSH connection with default retry.
84      * @return command execution status
85      */
86     public SaltstackResult connectNExecute(String cmd, boolean withRetry, long execTimeout)
87             throws IOException {
88
89         SaltstackResult result = new SaltstackResult();
90         ByteArrayOutputStream out = null;
91         ByteArrayOutputStream errs = null;
92         if (execTimeout >= 0) {
93             sshConnection.setExecTimeout(execTimeout);
94         }
95
96         try {
97             if (withRetry) {
98                 sshConnection.connectWithRetry();
99             } else {
100                 sshConnection.connect();
101             }
102             out = new ByteArrayOutputStream();
103             errs = new ByteArrayOutputStream();
104             int resultCode = sshConnection.execCommand(cmd, out, errs);
105             sshConnection.disconnect();
106             if (resultCode != 0) {
107                 return sortExitStatus(resultCode, errs.toString(), cmd);
108             }
109             result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
110             result.setStatusMessage("Success");
111             result.setOutputMessage(out);
112         } catch (SshException io) {
113             if (io.toString().equalsIgnoreCase("Authentication failed")) {
114                 logger.error(io.toString());
115                 result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
116                 result.setStatusMessage(io.toString());
117                 return result;
118             }
119             logger.error("Caught Exception", io);
120             result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
121             result.setStatusMessage(io.getMessage());
122         } catch (Exception io) {
123             logger.error("Caught Exception", io);
124             result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
125             result.setStatusMessage(io.getMessage());
126         } finally {
127             if (out != null) {
128                 out.close();
129             }
130             if (errs != null) {
131                 errs.close();
132             }
133         }
134         return result;
135     }
136
137     public SaltstackResult sortExitStatus(int exitStatus, String errMess, String cmd) {
138         SaltstackResult result = new SaltstackResult();
139         if (exitStatus == 255 || exitStatus == 1) {
140             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
141                     + "]. Exit Code " + exitStatus + " and Error message : " +
142                     "Malformed configuration. " + errMess;
143             logger.error(errMessage);
144             result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue());
145             result.setStatusMessage(errMessage);
146         } else if (exitStatus == 5 || exitStatus == 65) {
147             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
148                     + "]. Exit Code " + exitStatus + " and Error message : " +
149                     "Host not allowed to connect. " + errMess;
150             logger.error(errMessage);
151             result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
152             result.setStatusMessage(errMessage);
153         } else if (exitStatus == 67 || exitStatus == 73) {
154             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
155                     + "]. Exit Code " + exitStatus + " and Error message : " +
156                     "Key exchange failed. " + errMess;
157             logger.error(errMessage);
158             result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue());
159             result.setStatusMessage(errMessage);
160         } else {
161             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
162                     + "]. Exit Code " + exitStatus + " and Error message : " + errMess;
163             logger.error(errMessage);
164             result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
165             result.setStatusMessage(errMessage);
166         }
167         return result;
168     }
169 }