Documentationcurrent version
Help us improve the docs by fixing typos and proposing enhancements.

Nikita

Action "ssh.open"

Initialize an SSH connection.

Examples

Once an SSH connection is establish, it is possible to retrieve the connection by calling the ssh action. If no ssh connection is available, it will simply return null.

nikita
.ssh.open({
  host: 'localhost',
  user: 'my_account',
  password: 'my_secret'
})
.call(function(){
  assert(!!@ssh(), true)
})
.execute({
  metadata: {
    header: 'Print remote hostname'
  },
  command: 'hostname'
})
.ssh.close()

Set the ssh option to null or false to disabled SSH and force an action to be executed locally:

nikita
.ssh.open({
  host: 'localhost',
  user: 'my_account',
  password: 'my_secret'
})
.call({ssh: false}, function(){
  assert(@ssh(config.ssh), null)
})
.execute({
  ssh: false,
  metadata: {
    header: 'Print local hostname'
  },
  command: 'hostname'
})
.ssh.close()

It is possible to group all the config properties inside the ssh property. This is provided for conveniency and is often used to pass ssh information when initializing the session.

require('nikita')({
  ssh: {
    host: 'localhost',
    user: 'my_account',
    password: 'my_secret'
  }
})
.ssh.open()
.call(function({config}){
  assert(!!@ssh(), true)
})
.ssh.close()

Hooks

on_action = ({config}) ->
  config.private_key ?= config.privateKey
  # Define host from ip
  if config.ip and not config.host
    config.host = config.ip
  # Default root properties
  config.root ?= {}
  if config.root.ip and not config.root.host
    config.root.host = config.root.ip
  config.root.host ?= config.host
  config.root.port ?= config.port

Schema definitions

Configuration propeties are transfered as is to the ssh2 module to create a new SSH connection. Only will they be converted from snake case to came case. It is also possible to pass all the properties through the ssh property.

definitions =
  config:
    type: 'object'
    properties:
      'host':
        type: 'string'
        anyOf: [{format: 'ipv4'}, {format: 'hostname'}]
        default: '127.0.0.1'
        description: '''
        Hostname or IP address of the remote server.
        '''
      'ip':
        type: 'string'
        description: '''
        IP address of the remote server, used if `host` isn't already defined.
        '''
      'password':
        type: 'string'
        description: '''
        Password of the user used to authenticate and create the SSH
        connection.
        '''
      'port':
        type: 'integer'
        default: 22
        description: '''
        Port of the remote server.
        '''
      'private_key':
        type: 'string'
        description: '''
        Content of the private key used to authenticate the user and create
        the SSH connection. It is only used if `password` is not provided.
        '''
      'private_key_path':
        type: 'string'
        default: '~/.ssh/id_rsa'
        description: '''
        Local file location of the private key used to authenticate the user
        and create the SSH connection. It is only used if `password` and
        `private_key` are not provided.
        '''
      'root':
        $ref: 'module://@nikitajs/core/src/actions/ssh/root'
        description: '''
        Configuration passed to `nikita.ssh.root` to enable password-less root
        login.
        '''
      'username':
        type: 'string'
        default: 'root'
        description: '''
        Username of the user used to authenticate and create the SSH
        connection.
        '''

Handler

handler = ({config, parent: {state}, tools: {log}}) ->
  # Validate authentication
  throw utils.error 'NIKITA_SSH_OPEN_NO_AUTH_METHOD_FOUND', [
    'unable to authenticate the SSH connection,'
    'one of the "private_key", "password", "private_key_path"'
    'configuration properties must be provided'
  ] unless config.private_key or config.password or config.private_key_path
  # Read private key if option is a path
  unless config.private_key or config.password
    log message: "Read Private Key from: #{config.private_key_path}", level: 'DEBUG'
    location = await utils.tilde.normalize config.private_key_path
    try
      {data: config.private_key} = await fs.readFile location, 'ascii'
    catch err
      throw Error "Private key doesnt exists: #{JSON.stringify location}" if err.code is 'ENOENT'
      throw err
  # Establish connection
  try
    log message: "Read Private Key: #{JSON.stringify config.private_key_path}", level: 'DEBUG'
    conn = await connect config
    # state['nikita:ssh:connection'] = conn
    log message: "Connection is established", level: 'INFO'
    return ssh: conn
  catch err
    log message: "Connection failed", level: 'WARN'
  # Enable root access
  if config.root.username
    log message: "Bootstrap Root Access", level: 'INFO'
    await @ssh.root config.root
  log message: "Establish Connection: attempt after enabling root access", level: 'DEBUG'
  await @call $retry: 3, ->
    conn = await connect config
    # state['nikita:ssh:connection'] = conn
    ssh: conn

Exports

module.exports =
  handler: handler
  hooks:
    on_action: on_action
  metadata:
    definitions: definitions

Dependencies

connect = require 'ssh2-connect'
fs = require('fs').promises
utils = require '../../utils'
Edit on GitHub
Navigate
About

Nikita is an open source project hosted on GitHub and developed by Adaltas.