Release version 1.1.0 of sli/plugins
[ccsdk/sli/plugins.git] / sshapi-call-node / provider / src / main / java / org / onap / ccsdk / sli / plugins / sshapicall / SshApiCallNode.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) 2018 Samsung Electronics. All rights
8                         reserved.
9  * ================================================================================
10  * Modifications Copyright © 2018 IBM
11  * ================================================================================
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *      http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  *
24  * ============LICENSE_END=========================================================
25  */
26
27 package org.onap.ccsdk.sli.plugins.sshapicall;
28
29 import java.io.ByteArrayOutputStream;
30 import java.util.Map;
31
32 import org.onap.appc.adapter.ssh.SshAdapter;
33 import org.onap.appc.adapter.ssh.SshConnection;
34 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
35 import com.att.eelf.configuration.EELFLogger;
36 import com.att.eelf.configuration.EELFManager;
37 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
38 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
39 import org.onap.ccsdk.sli.plugins.sshapicall.model.AuthType;
40 import org.onap.ccsdk.sli.plugins.sshapicall.model.Parameters;
41 import org.onap.ccsdk.sli.plugins.sshapicall.model.ParseParam;
42
43
44 public class SshApiCallNode implements SvcLogicJavaPlugin {
45
46     private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
47
48     /**
49      * Output parameter - SSH command execution status.
50      */
51     private String PARAM_OUT_status = "sshApi.call.node.status";
52
53     /**
54      * Output parameter - content of SSH command stdout.
55      */
56     private String PARAM_OUT_stdout = "sshApi.call.node.stdout";
57
58     /**
59      * Output parameter - content of SSH command stderr.
60      */
61     private String PARAM_OUT_stderr = "sshApi.call.node.stderr";
62
63     /**
64      * Testing parameter - content of mocked SSH.
65      */
66     private boolean PARAM_TEST_MODE = false;
67     private String PARAM_OUT_MESSAGE = "TestOut";
68
69
70     /**
71      * Default success status.
72      */
73     private int DEF_SUCCESS_STATUS = 0;
74
75
76
77     private SshAdapter sshAdapter;
78
79     /**
80      * Used for jUnit test and testing interface
81      */
82     public SshApiCallNode(boolean mode) {
83         PARAM_TEST_MODE = mode;
84     }
85
86     public SshApiCallNode() {
87         PARAM_TEST_MODE = false;
88     }
89
90     public void setSshAdapter(SshAdapter sshAdapter) {
91         this.sshAdapter = sshAdapter;
92     }
93
94     /**
95      * Allows Directed Graphs  the ability to interact with SSH APIs.
96      * @param params HashMap<String,String> of parameters passed by the DG to this function
97      * <table border="1">
98      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
99      *  <tbody>
100      *      <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
101      *      <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
102      *      <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
103      *      <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
104      *      <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
105      *      <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
106      *      <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
107      *      <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
108      *      <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
109      *      <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
110      *      <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
111      *      <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
112      *      <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
113      *      <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
114      *               These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
115      *      <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
116      *               The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
117      *               This attribute can be used to generate files that a command may require as part of execution.</td></tr>
118      *  </tbody>
119      * </table>
120      * Exec remote command over SSH. Return command execution status.
121      * Command output is written to out or err stream.
122      *
123      * @param ctx Reference to context memory
124      */
125
126     public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
127         execSshCommand(params, ctx, false);
128     }
129
130     private void execSshCommand(Map<String, String> params, SvcLogicContext ctx, boolean withPty) throws SvcLogicException {
131         ParseParam parser = new ParseParam();
132         Parameters p = parser.getParameters(params);
133         logger.debug("=> Connecting to SSH server...");
134         SshConnection sshConnection = null;
135         int status = -1;
136         ByteArrayOutputStream stdout = new ByteArrayOutputStream();
137         ByteArrayOutputStream stderr = new ByteArrayOutputStream();
138         String stdoutRes = "";
139         String stderrRes = "";
140         try {
141             if (!PARAM_TEST_MODE) {
142                 sshConnection = getSshConnection(p);
143                 sshConnection.connect();
144                 logger.debug("=> Connected to SSH server...");
145                 logger.debug("=> Running SSH command...");
146                 sshConnection.setExecTimeout(p.sshExecTimeout);
147                 if (withPty) {
148                     status = sshConnection.execCommandWithPty(parser.makeCommand(params), stdout);
149                     stderr = stdout;
150                 }
151                 else
152                     status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
153                 stdoutRes = stdout.toString();
154                 stderrRes = stderr.toString();
155
156             } else {
157                 if (("true").equalsIgnoreCase(params.get("TestFail")))
158                     status = 202;
159                 else
160                     status = DEF_SUCCESS_STATUS;
161                 stdoutRes = params.get(PARAM_OUT_MESSAGE);
162             }
163             logger.debug("=> executed SSH command");
164
165             if(status == DEF_SUCCESS_STATUS) {
166                 parser.parseOutput(ctx, stdoutRes);
167             }
168             ctx.setAttribute(PARAM_OUT_status, String.format("%01d", status));
169             ctx.setAttribute(PARAM_OUT_stdout, stdoutRes);
170             ctx.setAttribute(PARAM_OUT_stderr, stderrRes);
171         } catch (Exception e){
172             throw new SvcLogicException("Exception in SSH adaptor : " + e.getMessage());
173         } finally {
174             if (sshConnection != null)
175                sshConnection.disconnect();
176         }
177     }
178
179     private SshConnection getSshConnection(Parameters p) throws SvcLogicException {
180         if (p.authtype == AuthType.BASIC)
181             return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
182         // This is not supported yet in the API, patch has already been added to APPC
183         else if (p.authtype == AuthType.KEY){
184             throw new SvcLogicException("SSH Key based Auth method not supported");
185         }
186         else if (p.authtype == AuthType.NONE){
187             throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
188         }
189         else if (p.authtype == AuthType.UNSPECIFIED){
190             if (p.sshapiUser != null && p.sshapiPassword != null)
191                 return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
192             else if (p.sshKey != null)
193                 throw new SvcLogicException("SSH Key based Auth method not supported");
194         }
195         throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
196     }
197
198
199     /**
200      * Allows Directed Graphs  the ability to interact with SSH APIs.
201      * @param params HashMap<String,String> of parameters passed by the DG to this function
202      * <table border="1">
203      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
204      *  <tbody>
205      *      <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
206      *      <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
207      *      <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
208      *      <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
209      *      <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
210      *      <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
211      *      <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
212      *      <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
213      *      <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
214      *      <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
215      *      <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
216      *      <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
217      *      <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
218      *      <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
219      *               These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
220      *      <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
221      *               The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
222      *               This attribute can be used to generate files that a command may require as part of execution.</td></tr>
223      *  </tbody>
224      * </table>
225      * Exec remote command over SSH. Return command execution status.
226      * Command output is written to out or err stream.
227      *
228      * @param ctx Reference to context memory
229      */
230
231     public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
232         execCommand(params, ctx);
233         parseResponse(ctx);
234     }
235
236     private void parseResponse (SvcLogicContext ctx) throws SvcLogicException {
237         int status = Integer.parseInt(ctx.getAttribute(PARAM_OUT_status));
238         if(status != DEF_SUCCESS_STATUS) {
239             StringBuilder errmsg = new StringBuilder();
240             errmsg.append("SSH command returned error status [").append(status).append(']');
241             String stderr = ctx.getAttribute(PARAM_OUT_stderr);
242             if((stderr != null) && !stderr.isEmpty()) {
243                 errmsg.append(". Error: [").append(stderr).append(']');
244             }
245             throw new SvcLogicException(errmsg.toString());
246         }
247     }
248
249     /**
250      * Allows Directed Graphs  the ability to interact with SSH APIs.
251      * @param params HashMap<String,String> of parameters passed by the DG to this function
252      * <table border="1">
253      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
254      *  <tbody>
255      *      <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
256      *      <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
257      *      <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
258      *      <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
259      *      <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
260      *      <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
261      *      <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
262      *      <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
263      *      <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
264      *      <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
265      *      <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
266      *      <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
267      *      <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
268      *      <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
269      *               These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
270      *      <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
271      *               The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
272      *               This attribute can be used to generate files that a command may require as part of execution.</td></tr>
273      *  </tbody>
274      * </table>
275      * Exec remote command over SSH. Return command execution status.
276      * Command output is written to out or err stream.
277      *
278      * @param ctx Reference to context memory
279      */
280     public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
281         execSshCommand(params, ctx, true);
282     }
283 }