The SSH Plugin

Todo

Write documentation on ssh.js

ssh.py - A plugin for Gate One that adds additional SSH-specific features.

Hooks

This Python plugin file implements the following hooks:

hooks = {
    'Web': [(r"/ssh", KnownHostsHandler)],
    'WebSocket': {
        'ssh_get_connect_string': get_connect_string,
        'ssh_execute_command': ws_exec_command,
        'ssh_get_identities': get_identities,
        'ssh_get_public_key': get_public_key,
        'ssh_get_private_key': get_private_key,
        'ssh_get_host_fingerprint': get_host_fingerprint,
        'ssh_gen_new_keypair': generate_new_keypair,
        'ssh_store_id_file': store_id_file,
        'ssh_delete_identity': delete_identity,
        'ssh_set_default_identities': set_default_identities
    },
    'Escape': opt_esc_handler,
    'Auth': create_user_ssh_dir
}

Docstrings

exception ssh.SSHMultiplexingException[source]

Called when there's a failure trying to open a sub-shell via OpenSSH's Master mode multiplexing capability.

exception ssh.SSHExecutionException[source]

Called when there's an error trying to execute a command in the slave.

exception ssh.SSHKeygenException[source]

Called when there's an error trying to generate a public/private keypair.

exception ssh.SSHKeypairException[source]

Called when there's an error trying to save public/private keypair or certificate.

exception ssh.SSHPassphraseException[source]

Called when we try to generate/decode something that requires a passphrase but no passphrase was given.

ssh.get_ssh_dir(tws)[source]

Given a gateone.TerminalWebSocket (tws) instance, return the current user's ssh directory

ssh.open_sub_channel(term, tws)[source]

Opens a sub-channel of communication by executing a new shell on the SSH server using OpenSSH's Master mode capability (it spawns a new slave) and returns the resulting termio.Multiplex instance. If a slave has already been opened for this purpose it will re-use the existing channel.

ssh.wait_for_prompt(term, cmd, errorback, callback, m_instance, matched)[source]

Called by termio.Multiplex.expect() inside of execute_command(), clears the screen and executes cmd. Also, sets an expect() to call get_cmd_output() when the end of the command output is detected.

ssh.get_cmd_output(term, errorback, callback, m_instance, matched)[source]

Captures the output of the command executed inside of wait_for_prompt() and calls callback if it isn't None.

ssh.terminate_sub_channel(m_instance)[source]

Calls m_instance.terminate() and deletes it from the OPEN_SUBCHANNELS dict.

ssh.timeout_sub_channel(m_instance)[source]

Called when the sub-channel times out by way of an termio.Multiplex.expect pattern that should never match anything.

ssh.got_error(m_instance, match=None, term=None, cmd=None, tws=None)[source]

Called if execute_command() encounters a problem/timeout.

match is here in case we want to use it for a positive match of an error.

ssh.execute_command(term, cmd, callback=None, tws=None)[source]

Execute the given command (cmd) on the given term using the existing SSH tunnel (taking advantage of Master mode) and call callback with the output of said command and the current termio.Multiplex instance as arguments like so:

callback(output, m_instance)

If callback is not provided then the command will be executed and any output will be ignored.

Note

This will not result in a new terminal being opened on the client--it simply executes a command and returns the result using the existing SSH tunnel.

ssh.send_result(tws, term, cmd, output, m_instance)[source]

Called by ws_exec_command() when the output of the executed command has been captured successfully. Writes a message to the client with the command's output and some relevant metadata.

ssh.ws_exec_command(settings, tws)[source]

Takes the necessary variables from settings and calls execute_command().

settings should be a dict that contains a 'term' and a 'cmd' to execute.

Tip

This function can be used to quickly execute a command and return its result from the client over an existing SSH connection without requiring the user to enter their password! See execRemoteCmd() in ssh.js.

class ssh.KnownHostsHandler(application, request, **kwargs)[source]

This handler allows the client to view, edit, and upload the known_hosts file associated with their user account.

get(*args, **kwargs)[source]

Determine what the user is asking for and call the appropriate method.

post(*args, **kwargs)[source]

Determine what the user is updating by checking the given arguments and proceed with the update.

_return_known_hosts()[source]

Returns the user's known_hosts file in text/plain format.

_save_known_hosts(known_hosts)[source]

Save the given known_hosts file.

ssh.get_connect_string(term, tws)[source]

Writes the connection string associated with term to the WebSocket like so:

{'sshjs_reconnect': {*term*: <connection string>}}

In ssh.js we attach an action (aka handler) to GateOne.Net.actions for 'sshjs_reconnect' messages that attaches the connection string to GateOne.terminals[*term*]['sshConnectString']

ssh.get_key(name, public, tws)[source]

Returns the private SSH key associated with name to the client. If public is True, returns the public key to the client.

ssh.get_public_key(name, tws)[source]

Returns the user's public key file named name.

ssh.get_private_key(name, tws)[source]

Returns the user's private key file named name.

ssh.get_host_fingerprint(settings, tws)[source]

Returns a the hash of the given host's public key by making a remote connection to the server (not just by looking at known_hosts).

ssh.generate_new_keypair(settings, tws)[source]

Calls openssh_generate_new_keypair() or dropbear_generate_new_keypair() depending on what's available on the system.

ssh.overwrite(m_instance, match)[source]

Called if we get asked to overwrite an existing keypair.

ssh.openssh_generate_new_keypair(name, path, keytype=None, passphrase='', bits=None, comment='', tws=None)[source]

Generates a new private and public key pair--stored in the user's directory using the given name and other optional parameters (using OpenSSH).

If keytype is given, it must be one of "ecdsa", "rsa" or "dsa" (case insensitive). If keytype is "rsa" or "ecdsa", bits may be specified to specify the size of the key.

Note

Defaults to generating a 521-byte ecdsa key if OpenSSH is version 5.7+. Otherwise a 2048-bit rsa key will be used.

ssh.dropbear_generate_new_keypair(name, path, keytype=None, passphrase='', bits=None, comment='', tws=None)[source]

Note

Not implemented yet

ssh.openssh_generate_public_key(path, passphrase=None, settings=None, tws=None)[source]

Generates a public key from the given private key at path. If a passphrase is provided, it will be used to generate the public key (if necessary).

ssh.store_id_file(settings, tws=None)[source]

Stores the given settings['private'] and/or settings['public'] keypair in the user's ssh directory as settings['name'] and/or settings['name'].pub, respectively. Either file can be saved independent of each other (in case this function needs to be called multiple times to save each respective file).

Also, a settings['certificate'] may be provided to be saved along with the private and public keys. It will be saved as settings['name']-cert.pub.

Note

I've found the following website helpful in understanding how to use OpenSSH with SSL certificates: http://blog.habets.pp.se/2011/07/OpenSSH-certificates

Tip

Using signed-by-a-CA certificates is very handy because allows you to revoke the user's SSH key(s). e.g. If they left the company.

ssh.delete_identity(name, tws)[source]

Removes the identity associated with name. For example if name is 'testkey', 'testkey' and 'testkey.pub' would be removed from the user's ssh directory (and 'testkey-cert.pub' if present).

ssh.get_identities(anything, tws)[source]

Sends a message to the client with a list of the identities stored on the server for the current user.

anything is just there because the client needs to send something along with the 'action'.

ssh.set_default_identities(identities, tws)[source]

Given a list of identities, mark them as defaults to use in all outbound SSH connections by writing them to <user's ssh dir>/.default_ids. If identities is empty, no identities will be used in outbound connections.

Note

Whenever this function is called it will overwrite whatever is in default_ids.

ssh.opt_esc_handler(text, tws)[source]

Handles text passed from the special optional escape sequance handler. We use it to tell ssh.js what the SSH connection string is so it can use that information to duplicate sessions (if the user so desires). For reference, the specific string which will call this function from a terminal app is:

\x1b]_;ssh|<whatever>
ssh.create_user_ssh_dir(tws, current_user, settings)[source]

To be called by the 'Auth' hook that gets called after the user is done authenticating, ensures that the <user's dir>/ssh directory exists.

Table Of Contents

Previous topic

The Playback Plugin

Next topic

The Example Plugin

This Page