summaryrefslogtreecommitdiffstats
path: root/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
blob: 48469fdd5ce977419afba20c241378a01387a81e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*-
 * ============LICENSE_START=======================================================
 * ONAP : CCSDK
 * ================================================================================
 * Copyright (C) 2018 Samsung Electronics. All rights reserved.
 * ================================================================================
 *
 * =============================================================================
 * 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.
 *
 *
 * ============LICENSE_END=========================================================
 */

package org.onap.ccsdk.sli.adaptors.saltstack.impl;

import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * Returns a custom SSH client
 * - based on options
 * - can create one with ssl using an X509 certificate that does NOT have a known CA
 * - create one which trusts ALL SSL certificates
 * - return default sshclient (which only trusts known CAs from default cacerts file for process) this is the default
 * option
 **/
public class ConnectionBuilder {

    private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
    SshConnection sshConnection;

    /**
     * Constructor that initializes an ssh client based on username and password
     **/
    public ConnectionBuilder(String host, String port, String userName, String userPasswd) {
        sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd);
    }

    /**
     * Constructor that initializes an ssh client based on ssh certificate
     * This is still not supported in 1.3.0 version
     **/
    public ConnectionBuilder(String host, String port, String certFile) {
        sshConnection = new SshConnection(host, Integer.parseInt(port), certFile);
    }


    /**
     * 1. Connect to SSH server.
     * 2. Exec remote command over SSH. Return command execution status.
     * Command output is written to out or err stream.
     *
     * @param cmd Commands to execute
     * @return command execution status
     */
    public SaltstackResult connectNExecute(String cmd, long execTimeout) throws IOException {
        return connectNExecute(cmd, false, execTimeout);
    }

    /**
     * 1. Connect to SSH server with retry enabled.
     * 2. Exec remote command over SSH. Return command execution status.
     * Command output is written to out or err stream.
     *
     * @param cmd       Commands to execute
     * @param withRetry make a SSH connection with default retry.
     * @return command execution status
     */
    public SaltstackResult connectNExecute(String cmd, boolean withRetry, long execTimeout)
            throws IOException {

        SaltstackResult result = new SaltstackResult();
        ByteArrayOutputStream out = null;
        ByteArrayOutputStream errs = null;
        if (execTimeout >= 0) {
            sshConnection.setExecTimeout(execTimeout);
        }

        try {
            if (withRetry) {
                sshConnection.connectWithRetry();
            } else {
                sshConnection.connect();
            }
            out = new ByteArrayOutputStream();
            errs = new ByteArrayOutputStream();
            int resultCode = sshConnection.execCommand(cmd, out, errs);
            sshConnection.disconnect();
            if (resultCode != 0) {
                return sortExitStatus(resultCode, errs.toString(), cmd);
            }
            result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
            result.setStatusMessage("Success");
            result.setOutputMessage(out);
        } catch (SshException io) {
            if (io.toString().equalsIgnoreCase("Authentication failed")) {
                logger.error(io.toString());
                result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
                result.setStatusMessage(io.toString());
                return result;
            }
            logger.error("Caught Exception", io);
            result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
            result.setStatusMessage(io.getMessage());
        } catch (Exception io) {
            logger.error("Caught Exception", io);
            result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
            result.setStatusMessage(io.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
            if (errs != null) {
                errs.close();
            }
        }
        return result;
    }

    /**
    * Print Reasonable error messages based on SSH Exit status code
    * */
    public SaltstackResult sortExitStatus(int exitStatus, String errMess, String cmd) {
        SaltstackResult result = new SaltstackResult();
        if (exitStatus == 255 || exitStatus == 1) {
            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                    + "]. Exit Code " + exitStatus + " and Error message : " +
                    "Malformed configuration. " + errMess;
            logger.error(errMessage);
            result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue());
            result.setStatusMessage(errMessage);
        } else if (exitStatus == 5 || exitStatus == 65) {
            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                    + "]. Exit Code " + exitStatus + " and Error message : " +
                    "Host not allowed to connect. " + errMess;
            logger.error(errMessage);
            result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
            result.setStatusMessage(errMessage);
        } else if (exitStatus == 67 || exitStatus == 73) {
            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                    + "]. Exit Code " + exitStatus + " and Error message : " +
                    "Key exchange failed. " + errMess;
            logger.error(errMessage);
            result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue());
            result.setStatusMessage(errMessage);
        } else {
            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                    + "]. Exit Code " + exitStatus + " and Error message : " + errMess;
            logger.error(errMessage);
            result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
            result.setStatusMessage(errMessage);
        }
        return result;
    }
}