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 * 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
16 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 * ============LICENSE_END=========================================================
27 package org.onap.ccsdk.sli.plugins.sshapicall;
29 import java.io.ByteArrayOutputStream;
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;
44 public class SshApiCallNode implements SvcLogicJavaPlugin {
46 private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
49 * Output parameter - SSH command execution status.
51 private String PARAM_OUT_status = "sshApi.call.node.status";
54 * Output parameter - content of SSH command stdout.
56 private String PARAM_OUT_stdout = "sshApi.call.node.stdout";
59 * Output parameter - content of SSH command stderr.
61 private String PARAM_OUT_stderr = "sshApi.call.node.stderr";
64 * Testing parameter - content of mocked SSH.
66 private boolean PARAM_TEST_MODE = false;
67 private String PARAM_OUT_MESSAGE = "TestOut";
71 * Default success status.
73 private int DEF_SUCCESS_STATUS = 0;
77 private SshAdapter sshAdapter;
80 * Used for jUnit test and testing interface
82 public SshApiCallNode(boolean mode) {
83 PARAM_TEST_MODE = mode;
86 public SshApiCallNode() {
87 PARAM_TEST_MODE = false;
90 public void setSshAdapter(SshAdapter sshAdapter) {
91 this.sshAdapter = sshAdapter;
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
98 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
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>
120 * Exec remote command over SSH. Return command execution status.
121 * Command output is written to out or err stream.
123 * @param ctx Reference to context memory
126 public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
127 execSshCommand(params, ctx, false);
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;
136 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
137 ByteArrayOutputStream stderr = new ByteArrayOutputStream();
138 String stdoutRes = "";
139 String stderrRes = "";
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);
148 status = sshConnection.execCommandWithPty(parser.makeCommand(params), stdout);
152 status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
153 stdoutRes = stdout.toString();
154 stderrRes = stderr.toString();
157 if (("true").equalsIgnoreCase(params.get("TestFail")))
160 status = DEF_SUCCESS_STATUS;
161 stdoutRes = params.get(PARAM_OUT_MESSAGE);
163 logger.debug("=> executed SSH command");
165 if(status == DEF_SUCCESS_STATUS) {
166 parser.parseOutput(ctx, stdoutRes);
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());
174 if (sshConnection != null)
175 sshConnection.disconnect();
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");
186 else if (p.authtype == AuthType.NONE){
187 throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
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");
195 throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
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
203 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
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>
225 * Exec remote command over SSH. Return command execution status.
226 * Command output is written to out or err stream.
228 * @param ctx Reference to context memory
231 public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
232 execCommand(params, ctx);
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(']');
245 throw new SvcLogicException(errmsg.toString());
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
253 * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
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>
275 * Exec remote command over SSH. Return command execution status.
276 * Command output is written to out or err stream.
278 * @param ctx Reference to context memory
280 public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
281 execSshCommand(params, ctx, true);