Control CLI cookbook

This document provides step-by-step instructions for bootstrapping and enrolling RADKit Service, then adding and updating users and devices, over the network using the RADKit Control CLI.

Warning

This procedure is for illustration purposes only. There are many possible ways to deploy RADKit Service and to use RADKit Control; you may need to adjust the steps below depending on your particular situation. Please make sure that you have read the Service and Control documentation and performed thorough testing before you attempt such a deployment in production.

Prerequisites

The instructions assume that you are using Linux, macOS or WSL and are already familiar with RADKit Client and Service.

RADKit Control is part of the RADKit Service package. In other words, you must install RADKit Service on both the host where you want to deploy RADKit Service, and the host from which you want to remotely configure RADKit Service. Those do not have to be the same platform, but they do have to use the same version of RADKit.

Bootstrap the Service

  1. Open a command-line interface on the host where RADKit Service will be deployed.

  2. Bootstrap RADKit Service and set a superadmin password, then start the Service:

    $ radkit-service bootstrap
    ...
    Set up the superadmin user. You'll be asked to provide a superadmin password.
    Keep this password securely stored, as it will be impossible to recover it!
    Superadmin password (for new setup): *********
    Confirm: *********
    ...
    Bootstrapping is complete. The next step is to enroll with the RADKit Certificate Authority.
    You can now start the Service with 'radkit-service run' and log on to the WebUI as 'superadmin'.
    Alternatively, you can enroll through the CLI (see documentation for details).
    
    $ radkit-service run
    ...
    Superadmin password: *********   [correct]
    ...
    15:25:29.216Z INFO  | internal | UI and API listener started [addresses=['[::]'] secure_port=8081]
    15:25:29.325Z INFO  | internal | Running on https://[::]:8081 (CTRL + C to quit)
    

    Note

    It is also possible to simply start the un-bootstrapped Service using radkit-service run and then bootstrap remotely using radkit-control admin create --initial superadmin, however that method currently does not allow to verify the Service TLS certificate; it is therefore recommended to bootstrap the Service locally and export the webserver certificate or its fingerprint to ensure a properly secured deployment process.

  3. Write down the Service API TLS certificate fingerprint displayed in the logs on startup:

    13:59:05.364Z INFO  | internal | Webserver certificate fingerprint [fingerprint='b555...d358']`
    

    Warning

    Do not confuse the Webserver certificate fingerprint with the unrelated E2EE certificate fingerprint.

Set up Control

  1. Open a command-line interface on the host where RADKit Control will be used to remotely manage RADKit Service.

  2. Create a TOML configuration file for Control (see Settings management and Control settings for more information).

    First create the control directory under your RADKIT_DIRECTORY:

    $ mkdir -p ~/.radkit/control/
    

    Then create settings.toml within that directory and adjust the values to your situation:

    ~/.radkit/control/settings.toml
    [control]
    service_url = "https://my-radkit-service-host:8081/api/v1"
    admin_name = "superadmin"
    service_fingerprint = "b555...d358"
    
  3. Verify connectivity by issuing the system status subcommand:

    % radkit-control system status
    superadmin's password:
    {
       "success": true,
       "result": {
          "version": "...",
          "username": "superadmin",
          "bootstrapped": true,
          "cloud_rpc_enabled": true,
          "direct_rpc_enabled": true,
          "cloud": {
                "domain": "PROD",
                "base_url": "https://prod.radkit-cloud.cisco.com",
                "enrolled": false,
                "service_id": null,
                "connected": false,
                "connected_message": "DISCONNECTED"
          },
          "e2ee_sha256_fingerprint": "...",
          "webserver_sha256_fingerprint": "..."
       }
    }
    

Note "enrolled": false in the results. You can now proceed with enrolling the Service.

Enroll the Service

  1. Log on to RADKit Cloud from RADKit Client and generate an OTP for your Service:

    >>> client = sso_login("radkit-user@example.com")
    >>> client.grant_service_otp()
    ...
    -----------  -----------------------
    email        radkit-user@example.com
    serial       aaaa-bbbb-cccc
    otp          1234-2345-3456
    domain_name  PROD
    -----------  -----------------------
    ...
    

    The domain-qualified OTP is PROD:1234-2345-3456.

  2. Enroll the Service remotely using system enroll (this can take a few seconds):

    $ radkit-control system enroll PROD:1234-2345-3456
    superadmin's password:
    {
       "success": true,
       "result": "Service successfully enrolled and started"
    }
    
  3. Verify the output of system status:

    % radkit-control system status
    superadmin's password:
    {
       "success": true,
       "result": {
          "version": "...",
          "username": "superadmin",
          "bootstrapped": true,
          "cloud_rpc_enabled": true,
          "direct_rpc_enabled": true,
          "cloud": {
                "domain": "PROD",
                "base_url": "https://prod.radkit-cloud.cisco.com",
                "enrolled": true,
                "service_id": "aaaa-bbbb-cccc",
                "connected": true,
                "connected_message": "CONNECTED"
          },
          "e2ee_sha256_fingerprint": "...",
          "webserver_sha256_fingerprint": "..."
       }
    }
    

Note the presence of "enrolled": true, "service_id": "aaaa-bbbb-cccc" and "connected_message": "CONNECTED" in the results.

Create an admin account

  1. Create an admin account and set a password for it using admin create:

    $ radkit-control admin create --full-name "My Admin" myadmin
    Provide a password for myadmin:
    superadmin's password:
    {
       "success": true,
       "result": {
          "username": "myadmin",
          "email": "",
          "fullname": "My Admin",
          "description": ""
       }
    }
    
  2. Verify the list of admins using admin list:

    $ radkit-control admin list
    superadmin's password:
    {
       "success": true,
       "result": [
          {
                "username": "superadmin",
                "email": "",
                "fullname": "",
                "description": ""
          },
          {
                "username": "myadmin",
                "email": "",
                "fullname": "My Admin",
                "description": ""
          }
       ]
    }
    
  3. Set up Control to start using this new admin account by changing the admin_name setting:

    ~/.radkit/control/settings.toml
    [control]
    ...
    admin_name = "myadmin"
    
  4. Control is now going to prompt for the password of myadmin instead of superadmin.

Note

Only superadmin is allowed to manage other admin accounts. It is preferable to switch to another admin account if you are only going to manage remote users and devices, and restrict the use of superadmin to specific tasks, such as managing admins or starting the Service.

Create a remote user

Create and activate a remote user for yourself using user create:

% radkit-control user create --full-name "My User" --active forever radkit-user@example.com
superadmin's password:
{
   "success": true,
   "result": {
      "username": "radkit-user@example.com",
      "fullname": "My User",
      "description": "",
      "timeSliceMinutes": null,
      "expirationTimestamp": null,
      "labels": []
   }
}

Create, update and interact with a device

  1. Create and activate a single device using device create:

    % radkit-control device create --description "My first device" --active true \
      --terminal-username example my-csr2 example-csr2.example.com IOS_XE
    myadmin's password:
    Device SSH password:
    {
       "success": true,
       "result": {
          "uuid": "006c91de-27f2-44be-ac15-cdb17cd84f20",
          "name": "csr2",
          "host": "example-csr2.cisco.com",
          "deviceType": "IOS_XE",
          "description": "My first device",
          "labels": [],
          "jumphostUuid": null,
          "sourceKey": null,
          "sourceDevUuid": null,
          "metaData": [],
          "enabled": true,
          "terminal": {
                "port": 22,
                "connectionMethod": "SSH",
                "username": "example",
                "enableSet": false,
                "useInsecureAlgorithms": false,
                "useTunnelingIfJumphost": true,
                "provisioningVariant": "DEFAULT"
          },
          "netconf": null,
          "swagger": null,
          "http": null,
          "forwardedTcpPorts": ""
       }
    }
    

    Since you configured the device for Terminal/SSH access and did not pass --terminal-password ... on the command-line, you were prompted for the SSH password for the device. This is safer than typing the password in the clear and leaving it in the shell history and/or terminal scrollback buffer.

    The device was allocated a UUID by the Service, in our example 006c91de-27f2-44be-ac15-cdb17cd84f20. This will be the unique identifier by which you will refer to this device in RADKit Control.

  2. Try renaming the device using device update, specifying the device UUID:

    $ radkit-control device update --name csr2 006c91de-27f2-44be-ac15-cdb17cd84f20
    myadmin's password:
    {
       "success": true,
       ...
    }
    
  3. Start a RADKit Client, authenticate using SSO, and list the Service inventory:

    >>> c = sso_login("radkit-user@example.com")
    >>> s = c.service("aaaa-bbbb-cccc")
    19:07:08.794Z INFO  | internal | Connecting to forwarder [uri='wss://prod.radkit-cloud.cisco.com/forwarder-3/websocket/']
    19:07:08.887Z INFO  | internal | Connection to forwarder successful [uri='wss://prod.radkit-cloud.cisco.com/forwarder-3/websocket/']
    >>> s.inventory
    <radkit_client.sync.device.DeviceDict object at 0x10b1cddb0>
    name    host                    device_type    Terminal    Netconf    Swagger    HTTP    description      failed
    ------  ----------------------  -------------  ----------  ---------  ---------  ------  ---------------  --------
    csr2    example-csr2.cisco.com  IOS_XE         True        False      False      False   My first device  False
    
    Untouched inventory from service aaaa-bbbb-cccc.
    >>>
    
  4. Try interacting over SSH with the device you created:

    >>> device = service.inventory['csr2']
    >>> device.interactive()
    21:09:17.692Z INFO  | internal | Starting interactive session (will be closed when detached)
    21:09:17.998Z INFO  | internal | Session log initialized [filepath='.....log']
    
       Attaching to  example-csr2.cisco.com  ...
       Type:  ~.  to terminate.
              ~?  for other shortcuts.
       When using nested SSH sessions, add an extra  ~  per level of nesting.
    
    Warning: all sessions are logged. Never type passwords or other secrets, except at an echo-less password prompt.
    

Create multiple devices in bulk from a CSV source with terminal defined

  1. Add the option --help to radkit-control device bulk-create

% radkit-control device bulk-create --help

Usage: radkit-control device bulk-create [OPTIONS]

Create multiple devices using JSON. Provide json in a file with --input, or
directly with --json

Options:
--json-input FILENAME  JSON file to pass to the API
--json-data JSON       JSON text to pass to the API
--csv-input FILENAME   CSV file to pass to the API
--csv-data TEXT        CSV text to pass to the API
--json-template        Show JSON template
--csv-template         Show CSV template. Use `terminal`, `http`, `swagger`,
                        `netconf` or `labels` to generate substructures
--output FILENAME      Save JSON response to a file instead of displaying it
--compact-json         Output JSON response on one line
--help                 Show this message and exit.
  1. Based on the output, choose the option --csv-template to display it. You can complement this with terminal, http, snmp swagger, netconf or labels substructures. In this example we will test terminal, as shown below:

    % radkit-control device bulk-create --csv-template terminal
    
    name(mandatory),host(mandatory),deviceType(mandatory),description,jumphostUuid,sourceKey,sourceDevUuid,metaData,enabled,snmp,forwardedTcpPorts,terminal.port,terminal.connectionMethod,terminal.username,terminal.enableSet,terminal.useInsecureAlgorithms,terminal.useTunnelingIfJumphost,terminal.password,terminal.enable,terminal.privateKeyPassword,terminal.privateKey
    
    Example:
    name,host,deviceType,description
    test-router1,1.1.1.1,IOS_XE,test router1
    test-router2,1.1.1.2,IOS_XE,test router2
    
  2. Start building your csv file, first by understanding each field and what values are accepted:

    The mandatory fields are name, host and deviceType. The rest of the fields are optional they have default values specified. These options will take their default values if not provided by the user.

    Example format for file.csv contents:

    name(mandatory),host(mandatory),deviceType(mandatory),description,jumphostUuid,sourceKey,sourceDevUuid,metaData,enabled,forwardedTcpPorts,terminal.port,terminal.connectionMethod,terminal.username,terminal.enableSet,terminal.useInsecureAlgorithms,terminal.useTunnelingIfJumphost,terminal.password,terminal.enable,terminal.privateKeyPassword,terminal.privateKey
    asr9001,1.2.3.4,IOS_XR,test router1,,,,,True,,22,SSH,my-username,,,,my-strong-password,True,,
    test-router2,1.1.1.2,IOS_XE,test router2,,,,,,,,,,,,,,,,
    

    See Devices for more information on the fields and expected values.

    % radkit-control device bulk-create --csv-input file.csv
    superadmin's password:
    {
       "results": [....],
       "success": true,
       "count": 5,
       "success_count": 5
    }