Skip to content

SSH channel plugin

This channel plugin manages communications with execution environments that are accessed via SSH.

Configuration

This plugin has a configuration file (sshee.yaml by default) that describes the host, port, ssl_context, trusted_authorities, and logfile to use. It can also enable insecure logins.

The configuration file also specifies pools.

If no configuration file is found it will default to the following values:

apiVersion: opentestfactory.org/v1alpha1
kind: SSHServiceConfig
current-context: default
contexts:
- name: default
  context:
    port: 443
    host: 127.0.0.1
    ssl_context: adhoc
    eventbus:
      endpoint: https://127.0.0.1:38368
      token: invalid-token
    targets: []
pools:

Contexts

contexts lists the available contexts. Contexts have a name and a definition, context. Each context is described by the following items:

  • host (required): the host the service will bind to (a hostname or an IP address).
  • port (required): the port the service will listen to (a number).
  • ssl_context (required): either adhoc, a list of two items (certificate file path and private key file path), or disabled (not recommended, will switch to plain HTTP).
  • trusted_authorities (optional): a list of public key files and/or directories containing public key files, used for token validation.
  • enable_insecure_login (optional): allow for insecure (token-less) logins, if set to true (by default, insecure logins are disabled).
  • insecure_bind_address (optional, only used if enable_insecure_login is set to true): insecure logins, if enabled, are only allowed from a given address (127.0.0.1 by default).
  • eventbus (required): the event bus to use. A dictionary with two required entries, endpoint and token, and an optional entry, insecure-skip-tls-verify.
  • targets (required): a list of targets which are groups specified in pools.

Current context

current-context specifies which context entry to use. There can be any number of contexts specified in the configuration file, but there must be one and only one current context.

The current context must be in the list of contexts.

Pools

pools lists the available groups of execution environments. Each group (a pool) describes one or more execution environment.

Each execution environment is described by the following (possibly optional) items:

  • Either host or hosts: a host name (a string) or a list of host names (a list of strings), required.
  • username: a username on the execution environment (a string), required.
  • tags: what capabilities it provides (a list of strings), required. Amongst those capabilities, there must be one and only one of linux, macos, or windows. If that is not the case, the execution environment will be ignored.
  • port: a port (a number), 22 by default.
  • script_path: where to put temporary scripts (a string), '/tmp' by default for linux and macos execution environments, %TEMP% for windows environments.
  • key_filename: a file path (a string), required if using key authentication.
  • passphrase: a passphrase (a string), required if using key authentication and key has a passphrase.
  • password: a password (a string), required if using password authentication.
  • ssh_host_keys: a file path (a string), required if there is a list of allowed incoming hosts (typically specified if using the default missing host key policy, which is to reject unknown incoming connections).
  • missing_host_key_policy: a string, either auto-add or reject (reject by default).
  • namespaces: a string, a comma-separated list of namespaces (default by default).

You cannot specify both key_filename and password at the same time. Execution environments with an incorrect specification are ignored.

namespaces specifies the namespace(s) the execution environment is accessible from. It is a comma-separated list of namespace names or '*', in which case the execution environment will be accessible from all namespaces.

Example

A SSH channel requires targets and pools entries in order to prepare and dispatch execution commands.

In the following example the current context, default, can handle execution requests with a runs-on statement that is either ssh, linux, [ssh, linux], or [linux, ssh]. It cannot handle execution requests with other tags.

It cannot handle runs-on statements that are either windows, [ssh, windows], or [windows, ssh] due to the fact that the demo_target group is not specified in the context’s targets.

apiVersion: opentestfactory.org/v1alpha1
kind: SSHServiceConfig
current-context: default
contexts:
- name: default
  context:
    port: 443
    host: 127.0.0.1
    ssl_context: adhoc
    logfile: sshee.log
    eventbus:
      endpoint: https://127.0.0.1:38368
      token: invalid-token
    targets: [ssh_targets, ssh2_targets]
pools:
  demo_target:
  - host: demo.example.com
    username: demo
    password: 1234
    tags: [ssh, windows]
  ssh_targets:
  - host: dummy.example.com
    username: user
    password: secret
    tags: [ssh, linux]
    namespaces: '*'
  ssh2_targets:
  - host: host.example.com
    port: 22
    username: alice
    ssh_host_keys: /data/ssh/known_hosts
    key_filename: /data/ssh/example.pem
    missing_host_key_policy: reject
    tags: [ssh, linux]
    namespaces: ns1,ns2
  - hosts: [foo.example.com, bar.example.com]
    port: 22
    username: bob
    ssh_host_keys: /data/ssh/known_hosts
    key_filename: /data/ssh/secret.pem
    passphrase: secret
    missing_host_key_policy: auto-add
    tags: [ssh, linux]

Environment variables

The ssh channel uses non-interactive sessions. By default, sshd only exposes a basic set of environment variables.

There are two ways to overcome this:

  • Add SetEnv statements in your /etc/ssh/sshd_config configuration file (for example BASH_ENV=~/.profile)
  • Enable the PermitUserEnvironment (set it to yes, and restart your ssh server). That way, in the account you connect to with ssh, you can add a ~/.ssh/environment with your variables (or BASH_ENV, as above)

Usage

python3 -m opentf.plugins.sshee [--context context] [--config configfile]

Endpoints

This module exposes one endpoint:

  • /inbox (POST)

Whenever calling this endpoint, a signed token must be specified via the Authorization header.

This header will be of form:

Authorization: Bearer xxxxxxxx

It must be signed with one of the trusted authorities specified in the current context.