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