2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * =============================================================================
7 * Copyright (C) 2018 Samsung Electronics. All rights
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * ============LICENSE_END=========================================================
25 package org.onap.ccsdk.sli.plugins.sshapicall;
27 //import com.fasterxml.jackson.databind.ObjectMapper;
29 import java.io.ByteArrayOutputStream;
30 import java.util.Collections;
31 import java.util.HashSet;
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;
49 public class SshApiCallNode implements SvcLogicJavaPlugin {
51 private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
54 * Output parameter - SSH command execution status.
56 private String PARAM_OUT_status = "sshApi.call.node.status";
59 * Output parameter - content of SSH command stdout.
61 private String PARAM_OUT_stdout = "sshApi.call.node.stdout";
64 * Output parameter - content of SSH command stderr.
66 private String PARAM_OUT_stderr = "sshApi.call.node.stderr";
69 * Default success status.
71 private int DEF_SUCCESS_STATUS = 0;
73 private SshAdapter sshAdapter;
75 public void setSshAdapter(SshAdapter sshAdapter) {
76 this.sshAdapter = sshAdapter;
80 * Allows Directed Graphs the ability to interact with SSH APIs.
81 * @param params HashMap<String,String> of parameters passed by the DG to this function
83 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
85 * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
86 * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
87 * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
88 * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
89 * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
90 * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
91 * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
92 * <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>
93 * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
94 * <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>
95 * <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>
96 * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
97 * <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>
98 * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
99 * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
100 * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
101 * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
102 * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
105 * Exec remote command over SSH. Return command execution status.
106 * Command output is written to out or err stream.
108 * @param ctx Reference to context memory
111 public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
112 execSshCommand(params, ctx, false);
115 private void execSshCommand(Map<String, String> params, SvcLogicContext ctx, boolean withPty) throws SvcLogicException {
116 ParseParam parser = new ParseParam();
117 Parameters p = parser.getParameters(params);
118 logger.debug("=> Connecting to SSH server...");
119 SshConnection sshConnection = null;
121 sshConnection = getSshConnection(p);
122 sshConnection.connect();
123 logger.debug("=> Connected to SSH server...");
124 logger.debug("=> Running SSH command...");
125 sshConnection.setExecTimeout(p.sshExecTimeout);
126 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
127 ByteArrayOutputStream stderr = new ByteArrayOutputStream();
130 status = sshConnection.execCommandWithPty(parser.makeCommand(params), stdout);
134 status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
135 String stdoutRes = stdout.toString();
136 String stderrRes = stderr.toString();
137 logger.debug("=> executed SSH command");
139 if(status == DEF_SUCCESS_STATUS) {
140 parser.parseOutput(ctx, stdoutRes);
142 ctx.setAttribute(PARAM_OUT_status, String.format("%01d", status));
143 ctx.setAttribute(PARAM_OUT_stdout, stdoutRes);
144 ctx.setAttribute(PARAM_OUT_stderr, stderrRes);
145 } catch (Exception e){
146 throw new SvcLogicException("Exception in SSH adaptor : " + e.getMessage());
148 if (sshConnection != null)
149 sshConnection.disconnect();
153 private SshConnection getSshConnection(Parameters p) throws SvcLogicException {
154 if (p.authtype == AuthType.BASIC)
155 return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
156 // This is not supported yet in the API, patch has already been added to APPC
157 else if (p.authtype == AuthType.KEY){
158 //return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshKey);
159 throw new SvcLogicException("SSH Key based Auth method not supported");
161 else if (p.authtype == AuthType.NONE){
162 //return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshKey);
163 throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
165 else if (p.authtype == AuthType.UNSPECIFIED){
166 if (p.sshapiUser != null && p.sshapiPassword != null)
167 return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
168 else if (p.sshKey != null)
169 throw new SvcLogicException("SSH Key based Auth method not supported");
171 throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
176 * Allows Directed Graphs the ability to interact with SSH APIs.
177 * @param params HashMap<String,String> of parameters passed by the DG to this function
179 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
181 * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
182 * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
183 * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
184 * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
185 * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
186 * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
187 * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
188 * <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>
189 * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
190 * <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>
191 * <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>
192 * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
193 * <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>
194 * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
195 * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
196 * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
197 * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
198 * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
201 * Exec remote command over SSH. Return command execution status.
202 * Command output is written to out or err stream.
204 * @param ctx Reference to context memory
207 public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
208 execCommand(params, ctx);
209 ParseParam parser = new ParseParam();
210 String responsePrefix = parser.getStringParameters(params, parser.SSH_ResponsePrefix);
211 parseResponse(ctx, responsePrefix);
214 private void parseResponse (SvcLogicContext ctx, String responsePrefix) throws SvcLogicException {
215 int status = Integer.parseInt(ctx.getAttribute(PARAM_OUT_status));
216 if(status != DEF_SUCCESS_STATUS) {
217 StringBuilder errmsg = new StringBuilder();
218 errmsg.append("SSH command returned error status [").append(status).append(']');
219 String stderr = ctx.getAttribute(PARAM_OUT_stderr);
220 if((stderr != null) && !stderr.isEmpty()) {
221 errmsg.append(". Error: [").append(stderr).append(']');
223 throw new SvcLogicException(errmsg.toString());
228 * Allows Directed Graphs the ability to interact with SSH APIs.
229 * @param params HashMap<String,String> of parameters passed by the DG to this function
231 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
233 * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
234 * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
235 * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
236 * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
237 * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
238 * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
239 * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
240 * <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>
241 * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
242 * <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>
243 * <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>
244 * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
245 * <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>
246 * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
247 * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
248 * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
249 * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
250 * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
253 * Exec remote command over SSH. Return command execution status.
254 * Command output is written to out or err stream.
256 * @param ctx Reference to context memory
258 public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
259 execSshCommand(params, ctx, true);