Skip to main content
Version: 8 - Apfelstrudel

ConnectorTypeSSH

class connector_types.connector_type_ssh.ConnectorTypeSSH

Connect to a remote host using SSH and execute a script.

note

Cancelling an active execution created by an SSH connector might not be possible if the third party system, that is running the script, doesn't respond. In this case Cloudomation sends the signal to cancel the process on the third party system but as long as the script is running on said system, the execution status will be shown a running in Cloudomation. To cancel the execution you have to kill the process directly in the non-responsive system.

Input Schema

  • hostname

    Type: string

  • hostkey

    Type: anyOf

  • port

    Type: anyOf

  • username

    Type: string

  • password

    Type: anyOf

  • key

    The content of the ssh private keyfile used for authentication,

    currently only works with non-password protected keyfiles.

    Type: anyOf

  • script

    The script to run on the SSH host.

    Type: string

  • connect_tries

    How many times to try to connect.

    Type: integer

    Default: 3

  • connect_timeout

    How long to wait for a response from the server. Only applies after a successful connection.

    If a connection is impossible the connection fails immediately.

    Type: integer

    Default: 60

  • script_timeout

    Type: integer

    Default: 60

  • remove_cr

    Remove carriage-return (CR) characters from the report string.

    Type: boolean

    Default: True

  • remove_ansi_escapes

    Remove ANSI escape sequences from the report string.

    Type: boolean

    Default: True

  • use_shell

    If to log in interactively to the shell. If unset,

    a script file will be created and executed on the server.

    Type: boolean

  • temp_path

    Path to the temporary directory where script files will be stored.

    Type: string

    Default: /tmp

  • interpreter

    The interpreter to use when executing a script file.

    Type: string

    Default: /usr/bin/env bash -e

  • output_vars

    A list of shell variables which will be returned in the output_value of the connection.

    Type: array

  • copy_files

    A list of paths to files which will be copied to Cloudomation after the script ran.

    Type: array

  • output_files

    A list of paths to files which will be returned in the output_value of the connection.

    Type: array

  • encoding

    The character encoding used on the remote host.

    Type: string

    Default: utf-8

Output Schema

  • retcode

    Type: integer

  • report

    The outputs your script produced on the remote system.

    Type: string

  • handler_report

    Type: string

  • waiter_report

    Type: string

  • vars

    The content of all variables which were registered using #OUTPUT_VAR(variable) or set in the output_vars input.

    Type: object

    Additional Properties: True

    Pattern Properties:

    • .*

      Type: string

  • files

    The names and content of the output files which were registered using #OUTPUT_FILE(path) or set in the output_files input as well as names of the copy files which were registered using #COPY_FILE(path) or set in the copy_files input.

    Type: array

Constants

ssl_context_inputs = ['check_hostname', 'client_cert', 'client_key', 'server_ca']

Example

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
# Authenticate using private key
info_child = this.connect(
connector_type='SSH',
# public accessible name or IP
hostname='my-ssh-server',
# key to check host identity.
# can be read with "$ ssh-keyscan -t rsa <my-ssh-server>"
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script=(
'''
HOSTNAME=$(hostname)
USERNAME=$(id -un)
CPU=$(uname -p)
#OUTPUT_VAR(HOSTNAME)
#OUTPUT_VAR(USERNAME)
#OUTPUT_VAR(CPU)
'''
),
)

outputs = info_child.get('output_value')
hostname = outputs['vars']['HOSTNAME']
username = outputs['vars']['USERNAME']
cpu = outputs['vars']['CPU']

this.log(f'info_child was running on {hostname} using {cpu} as {username}')

# Authenticate using password
uptime_child = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
password='***',
script=(
'''
UPTIME=$(uptime -s)
#OUTPUT_VAR(UPTIME)
'''
),
)

outputs = uptime_child.get('output_value')
uptime = outputs['vars']['UPTIME']

this.log(f'{hostname} is up since {uptime}')

return this.success('all done')

More

Output variables

There are two ways how to define "output variables":

  • from the flow starting the connection, in the output_vars field of the input dictionary
  • from inside the connection, in the script field of the input dictionary

Output variables in output_vars

You can register shell variables as "output variables" in the output_vars field of the input dictionary, e.g.:

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script='''
VALUE=foo
''',
name='output_var',
output_vars=['VALUE'],
)
assert child_execution.get('output_value')['vars']['VALUE'] == 'foo'

Output variables in script

You can register shell variables as "output variables" using #OUTPUT_VAR(variable_name):

VARIABLE="some content"
#OUTPUT_VAR(VARIABLE)

The value of registered variables is available to the calling flow script in the var dictionary of the connection outputs:

outputs = connect(...).get('output_value')
variable = outputs['vars']['VARIABLE']
# `variable` contains "some content"

Output files

There are two ways how to define "output files":

  • from the flow starting the connection, in the output_files field of the input dictionary
  • from inside the connection, in the script field of the input dictionary

Output files in output_files

You can register files as "output files" in the output_files field of the input dictionary, e.g.:

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script='''
echo -n "spam" > file.txt
''',
name='output_var',
output_files=['file.txt'],
)
assert {'name': 'file.txt', 'content': 'spam'} in child_execution.get('output_value')['files']

Output files in script

You can register files as "output files" using #OUTPUT_FILE(filename):

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script='''
echo -n "egg" > file2.txt
#OUTPUT_FILE(file2.txt)
''',
name='output_var',
)
assert {'name': 'file2.txt', 'content': 'egg'} in child_execution.get('output_value')['files']

Copy files

There are two ways how to define "copy files":

  • from the flow starting the connection, in the copy_files field of the input dictionary
  • from inside the connection, in the script field of the input dictionary

Copy files in copy_files

You can register files as "copy files" in the copy_files field of the input dictionary, e.g.:

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script='''
echo -n "spam" > file.txt
''',
name='output_var',
copy_files=['file.txt'],
)
assert {'name': 'file.txt'} in child_execution.get('output_value')['files']
assert system.file('file.txt').get_text_content() == 'spam'

Copy files in script

You can register files as "copy files" using #COPY_FILE(filename):

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
script='''
echo -n "egg" > file2.txt
#COPY_FILE(file2.txt)
''',
name='output_var',
)
assert {'name': 'file2.txt'} in child_execution.get('output_value')['files']
assert system.file('file2.txt').get_text_content() == 'egg'

Source .profile or .bashrc on the remote.

By default no dotfiles are sourced by the connector. To source the .bashrc file using the bash shell change the interpreter to something like /bin/bash -ie to tell bash to run in interactive mode. Similarly, to source the .bash_profile file (refer to the bash documentation to find out which files will be sourced and in what order) run bash as if it was invoked as a login shell by specifying the -l flag: /bin/bash -le.

child_execution = this.connect(
connector_type='SSH',
hostname='my-ssh-server',
hostkey='ssh-rsa AAAAB3NzaC1yc2E...',
username='kevin',
key='-----BEGIN RSA PRIVATE KEY-----\nMII...',
interpreter='/bin/bash -ie',
script='''
true
''',
name='sourcing .bashrc',
)