This is a quick guide on how to turn SSH commands into a REST API service. The use-case may be remote administration of devices or equipment that does not offer a REST interface or making sure that access to SSH commands is restricted to selected external REST-based API clients only.
Python
The first thing needed is code of the service that will connect to SSH servers. Below is a service doing just that - it receives name of the command to execute and host to run in on, translating stdout and stderr of SSH commands into response documents which Zato in turn serializes to JSON.
It uses the sh library for SSH connections which means that each new one is started in a subprocess.
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
# stdlib
from traceback import format_exc
# sh
from sh import ssh
# Zato
from zato.server.service import Service
class SSHInvoker(Service):
""" Accepts an SSH command to run on a remote host and returns its output to caller.
"""
class SimpleIO:
input_required = 'host', 'command'
output_required = 'is_ok', 'cid'
output_optional = 'stdout', 'stderr'
skip_empty_keys = True
response_elem = None
def handle(self):
# Local aliases
host = self.request.input.host
command = self.request.input.command
# Correlation ID is always to be returned
self.response.payload.cid = self.cid
try:
# Run the command and collect output
output = ssh(host, command)
# Assign both stdout and stderr to response
self.response.payload.stdout = output.stdout
self.response.payload.stderr = output.stderr
except Exception:
# Catch any exception and log it
self.logger.warn('Exception caught (%s), e:`%s', self.cid, format_exc())
self.response.payload.is_ok = False
else:
# Everything went fine
self.response.payload.is_ok = True
Web-admin
In web-admin, let's go ahead and create an HTTP Basic Auth definition that a remote API client will authenticate against:
Now, the SSH service can be mounted on a newly created REST channel - note the security definition used and that data format is set to JSON.
Usage
At this point, everything is ready to use. For testing purposes, let's invoke the service from command line:
$ curl "api:8MbrHs2GHHQjw@localhost:11223/api/ssh" -d \
'{"host":"localhost", "command":"uptime"}'
{
"is_ok": true,
"cid": "27406f29c66c2ab6296bc0c0",
"stdout": " 09:45:42 up 37 min, 1 user, load average: 0.14, 0.27, 0.18\n"}
$
This completes it - the service is deployed and made accessible via a REST channel that can be invoked using JSON. Any command can be sent to any host and, assuming that SSH commands can be executed at all, their output will be returned to API callers in JSON responses.
from Planet Python
via read more
No comments:
Post a Comment