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.


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 =
        command = self.request.input.command

        # Correlation ID is always to be returned
        self.response.payload.cid = self.cid

            # 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

            # Everything went fine
            self.response.payload.is_ok = True


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.


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.