---
id: adding-devices
title: Adding Devices
sidebar_label: Adding Devices
keywords:
  [hyperglass, authentication, ssl, proxy, access list, prefix list, acl, help]
description: Adding devices to hyperglass
---

import Link from "@docusaurus/Link";
import R from "../src/components/Required";
import MiniNote from "../src/components/MiniNote";
import Code from "../src/components/JSXCode";

<div class="table--full-width" />

## Adding Devices

To add, as an example, a Cisco router, add the following to your `devices.yaml`, with the relevant details changed for your device:

```yaml title="devices.yaml"
routers:
  - name: New York City, NY
    address: 10.0.0.1
    network:
      name: production
      display_name: AS65000
    credential:
      username: username
      password: password
    port: 22
    nos: cisco_ios
    vrfs:
      - name: global
        default: true
        ipv4:
          source_address: 192.0.2.1
        ipv6:
          source_address: 2001:db8::1
```

## All Device Parameters

| Parameter           |  Type   | Description                                                                                                       |
| :------------------ | :-----: | :---------------------------------------------------------------------------------------------------------------- |
| <R/> `name`         | String  | Device's user-facing name.                                                                                        |
| <R/> `address`      | String  | Device management hostname or IP address.                                                                         |
| <R/> `network`      | String  | [Network Configuration](#network)                                                                                 |
| <R/> `port`         | Integer | TCP port used to connect to the device. `22` by default.                                                          |
| <R/> `nos`          | String  | Network Operating System. <MiniNote>Must be a <Link to="platforms">supported platform</Link>.</MiniNote>          |
| `structured_output` | Boolean | Disabled output parsing to structured data.                                                                       |
| `driver`            | String  | Override the device driver. Must be 'scrapli' or 'netmiko'.                                                       |
| <R/>`credential`    |         | [Device Credential Configuration](#credential)                                                                    |
| <R/>`vrfs`          |         | [Device VRF Configuration](#vrfs)                                                                                 |
| `proxy`             |         | [SSH Proxy Configuration](#proxy)                                                                                 |
| `ssl`               |         | [SSL Configuration](#ssl) for devices using [hyperglass-agent](https://github.com/thatmattlove/hyperglass-agent). |

### `network`

A network is only used for grouping. For example, if your network contains more than one ASN, you might want to group each device separately. Currently, you must define a network on each device.

| Parameter           |  Type  | Description                                                          |
| :------------------ | :----: | :------------------------------------------------------------------- |
| <R/> `name`         | String | The network's name. This name is only used by hyperglass internally. |
| <R/> `display_name` | String | The network's use-facing name.                                       |

### `proxy`

Any device that uses SSH (see [platforms](platforms) for breakdown) can be accessed through an intermediary SSH "proxy". The process is nearly identical to using local SSH tunneling, e.g. `ssh -L local_port:remote_device:remote_port username@proxy_server -p proxy_port`.

| Parameter         |  Type   | Default       | Description                                                                                                      |
| :---------------- | :-----: | :------------ | :--------------------------------------------------------------------------------------------------------------- |
| <R/> `name`       | String  |               | Proxy hostname.                                                                                                  |
| <R/> `address`    | String  |               | Proxy management hostname or IP address.                                                                         |
| <R/> `credential` |         |               | [Proxy Credential Configuration](#credential)                                                                    |
| `nos`             | String  | `'linux_ssh'` | Proxy's network operating system. <MiniNote>Must be a <Link to="platforms">supported platform</Link>.</MiniNote> |
| `port`            | Integer | `22`          | TCP port user to connect to the proxy.                                                                           |

:::important
Currently, only `linux_ssh` has been tested and validated for use as an SSH proxy.
:::

### `credential`

While all devices require a credential mapping, the credential values themselves may be used in different ways depending on the device NOS. For SSH devices, the credential is used as a typical SSH username and password.

For HTTP devices (i.e. devices using [hyperglass-agent](https://github.com/thatmattlove/hyperglass-agent)), the username is ignored and the password is used as a secret for [JSON Web Token](https://tools.ietf.org/html/rfc7519) encoding/decoding.

| Parameter       | Type   | Description                                                  |
| :-------------- | :----- | :----------------------------------------------------------- |
| <R/> `username` | String | Username                                                     |
| `password`      | String | Password <MiniNote>Passwords will never be logged</MiniNote> |
| `key`           | Path   | Path to SSH Private Key                                      |

To use SSH key authentication, simply specify the path to the SSH private key with `key:`. If the key is encrypted, set the private key's password to the with the `password:` field, and hyperglass will use it to decrypt the SSH key.

### `ssl`

HTTP devices may optionally use SSL for the connection between hyperglass and the device. This is **disabled** by default, which means devices will use unencrypted HTTP by default.

If SSL is enabled, the public key of the device must be provided in the form of an accessible absolute file path. With SSL enabled and a valid certificate specified, every connection to the device will use HTTPS in addition to payload encoding with [JSON Web Tokens](https://tools.ietf.org/html/rfc7519).

| Parameter   | Type    | Description                                                                                                                                                                                  |
| :---------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enable`    | Boolean | Enable or disable the use of SSL. <MiniNote>If enabled, a certificate file must be specified (hyperglass does not support connecting to a device over an unverified SSL session).</MiniNote> |
| <R/> `cert` | String  | Absolute path to agent's public RSA key.                                                                                                                                                     |

### `vrfs`

The VRFs section is a list of available VRFs for a given device. Each VRF may be configured with the following fields:

| Parameter      | Type    | Description                                                                                                                                                                                                                                                                                                                                            |
| :------------- | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <R/> `name`    | String  | The VRF's name, as known **by the device**. <MiniNote>hyperglass sends this field to the device for queries, so it needs to match the device's configuration. If this is the default/global routing table on the device, this value isn't sent to the device.</MiniNote>                                                                               |
| `display_name` | String  | The VRF's user-facing name. This field's value is visible in the UI. <MiniNote>If this is not specified, hyperglass will try to create a "pretty" display name based on the `name` field.</MiniNote>                                                                                                                                                   |
| `default`      | Boolean | Indicate that this VRF is the device's default/global routing table (more specifically, that it does not require specifying the VRF name when running commands).<MiniNote>If this is set to `true`, the `ipv4_default`/`ipv6_default` [command sets](commands.mdx). If set to `false`, the `ipv4_vpn`/`ipv6_vpn` command sets will be used.</MiniNote> |
| `info`         |         | [Per-VRF Contextual Help Configuration](#info)                                                                                                                                                                                                                                                                                                         |
| `ipv4`         |         | [VRF's IPv4 Configuration](#ipv4)                                                                                                                                                                                                                                                                                                                      |
| `ipv6`         |         | [VRF's IPv6 Configuration](#ipv6)                                                                                                                                                                                                                                                                                                                      |

#### `ipv4`

May be set to `null` to disable IPv4 for this VRF, on the parent device.

| Parameter             | Type    | Description                                                           |
| :-------------------- | :------ | :-------------------------------------------------------------------- |
| <R/> `source_address` | String  | Device's source IPv4 address for directed queries (ping, traceroute). |
| `force_cidr`          | Boolean | `true`                                                                | Convert IP host queries to actual advertised containing prefix length |
| `access_list`         |         | <Link to="#access_list">IPv4 Access List Configuration</Link>         |

#### `ipv6`

May be set to `null` to disable IPv6 for this VRF, on the parent device.

| Parameter             | Type    | Default | Description                                                                                                                             |
| :-------------------- | :------ | :------ | :-------------------------------------------------------------------------------------------------------------------------------------- |
| <R/> `source_address` | String  |         | Device's source IPv6 address for directed queries (ping, traceroute). This address must be surrounded by quotes. Ex. "0000:0000:0000::" |
| `force_cidr`          | Boolean | `true`  | Convert IP host queries to actual advertised containing prefix length                                                                   |
| `access_list`         |         |         | [IPv6 Access List Configuration](#access_list)                                                                                          |

:::note
The `force_cidr` option will ensure that a **BGP Route** query for an IP host (/32 IPv4, /128 IPv6) is converted to its containing prefix. For example, a query for `1.1.1.1` would be converted to a query for `1.1.1.0/24`. This is because not all platforms support a BGP lookup for a host (this is primary a problem with IPv6, but the option applies to both address families).

When `force_cidr`is set to `true`, hyperglass will perform a lookup via the [bgp.tools](https://bgp.tools) whois API to get the advertised prefix for an IP host.
:::

#### `access_list`

The `access_list` block can be thought of like a prefix-list from Cisco IOS. It is a list of rules, where the first matching rule is the action executed.

| Parameter      | Type    |    Default    | Description                                                                 |
| :------------- | :------ | :-----------: | :-------------------------------------------------------------------------- |
| <R/> `network` | String  |               | This rule's IPv4 or IPv6 base prefix                                        |
| `action`       | String  |  `'permit'`   | This rule's action. Must be `permit` or `deny`                              |
| `ge`           | Integer |      `0`      | To match this rule, the target prefix must be greater than or equal to `ge` |
| `le`           | Integer | `32` \| `128` | To match this rule, the target prefix must be less than or equal to `le`    |

#### `info`

Each VRF may enable, disable, or customize the contextual help menu for each enabled query type. The following parameters may be defined under any query type:

| Parameter | Type    | Default | Description                                                                                                                 |
| :-------- | :------ | :-----: | :-------------------------------------------------------------------------------------------------------------------------- |
| `enable`  | Boolean | `true`  | Enable or disable the help menu for this command.                                                                           |
| `file`    | String  |         | Path to a plain text or markdown file containing customized help information for this command.                              |
| `params`  | Object  |         | Any arbitrary key/value pairs where the value will replace any occurrences of the key when wrapped in braces (e.g. `{key}`) |

For example:

```yaml title="devices.yaml"
routers:
  - name: router01
    vrfs:
      - name: demo_vrf
        info:
        bgp_route:
          enable: true
          file: /etc/hyperglass/customer_bgp_route.md
          params:
            vrf_name: Customer A
        ping:
          enable: false
        bgp_community:
          enable: true
          file: /etc/hyperglass/customer_bgp_community.md
          params:
            vrf_name: Customer A
            community: "65000"
```

## Telnet

Telnet support is provided via the underlying device connection handling framework, [Netmiko](https://github.com/ktbyers/netmiko). To connect to a device via serial, add the suffix `_telnet` to the device's `nos` value and set the `port` value to `23`.

For example:

```yaml {3-4} title="devices.yaml"
routers:
    - name: router01
      nos: cisco_ios_telnet
      port: 23
      ...
```

## Full Example

Below is a full example with nearly every available knob turned:

```yaml title="devices.yaml"
routers:
  # HTTP/hyperglass-agent device
  - name: HTTP Router
    address: 192.0.2.1
    network:
      name: primary
      display_name: AS65000
    credential:
      username: madeup
      password: txeTTIqwhKSJi4V3tefXQASf5AyGZ6cPsycS9nYLpKk
    ssl:
      enable: true
      cert: /etc/hyperglass/certs/router01.pem
    port: 8080
    nos: frr
    vrfs:
      - name: global
        default: true
        ipv4:
          source_address: 192.0.2.1
          access_list:
            - network: 10.0.0.0/8
              action: deny
              ge: 8
              le: 32
            - network: 0.0.0.0/0
              action: permit
              le: 24 # Only allow /24 or smaller prefixes
        ipv6:
          source_address: 2001:db8::1
          access_list:
            - network: ::/0
              action: permit
    proxy: null

  # SSH/netmiko device
  - name: SSH Router
    address: 10.0.0.1
    network:
      name: primary
      display_name: AS65000
    credential:
      username: user
      password: pass
    port: 22
    nos: cisco_ios
    vrfs:
      - name: global
        default: true
        ipv4:
          source_address: 192.0.2.2
          access_list:
            - network: 10.0.0.0/8
              action: deny
              ge: 8
              le: 32
            - network: 0.0.0.0/0
              action: permit
        ipv6:
          source_address: 2001:db8::2
          access_list:
            - network: ::/0
              action: permit
              le: 64 # Only allow /64 or smaller prefixes
      - name: special_customer
        display_name: Customer Name
        ipv4:
          source_address: 172.16.0.1
          access_list:
            - network: 172.16.0.0/16
              action: allow
        ipv6: null # disable IPv6 for this VRF
        info:
          bgp_route:
            file: /etc/hyperglass/help/customer_bgp_route.md
            params:
              customer_name: Customer Name
    proxy:
      name: jump_server
      address: 10.0.1.100
      port: 22
      credential:
        username: user
        password: pass
      nos: linux_ssh
```

## YAML Anchors & Aliases

If you have a lot of devices with shared configuration parameters, you may want to look into **YAML Anchors and Aliases**. If you've never used them before, they can be pretty weird looking at first read. Atlassian [has a pretty decent guide](https://confluence.atlassian.com/bitbucket/yaml-anchors-960154027.html).

Here's an example of using this to share two sets of credentials among multiple devices:

```yaml title="devices.yaml"
my_credentials:
  - credential: &credential1
    username: madeup1
    password: gY018mR4gx4sVqc0
  - credential: &credential2
    username: madeup2
    password: 0eMEJ4ZpB6ofkiIF

routers:
  - name: router01
    credential: *credential1
  - name: router02
    credential: *credential2
  - name: router03
    credential: *credential1
  - name: router04
    credential: *credential2
```

:::important
Nothing other than the `routers` key is read by hyperglass. In the above example, `my_credentials` is just an arbitrary list of mappings, is completely optional, and can be named whatever you want.
:::

For a more complex example, here's an example of how to use YAML aliases & anchors to share a common VRF configuration among multiple devices, while overriding key variables such as the `source_address` key:

```yaml title="devices.yaml"
my_vrfs:
  - &default
    name: global
    default: true
    display_name: Global
    ipv4:
      access_list: &default_ipv4_acl
        - network: 10.0.0.0/8
          action: deny
        - network: 192.168.0.0/16
          action: deny
        - network: 172.16.0.0/12
          action: deny
        - network: 0.0.0.0/0
          action: permit
          ge: 8
          le: 24
    ipv6:
      access_list: &default_ipv6_acl
        - network: ::/0
          action: permit
          ge: 32
          le: 64
  - &customer_a
    name: customer_a
    default: false
    display_name: Customer A
    ipv4:
      access_list: &customer_a_ipv4_acl
        - network: 10.0.0.0/8
          action: permit
        - network: 0.0.0.0/0
          action: deny
    ipv6: null

routers:
  - name: router01
    vrfs:
      - <<: *default
        ipv4:
          source_address: 192.0.2.1
          access_list: *default_ipv4_acl
        ipv6:
          source_address: 2001:db8::1
          access_list: *default_ipv6_acl
      - <<: *customer_a
        ipv4:
          source_address: 10.0.0.1
          access_list: *customer_a_ipv4_acl

  - name: router02
    vrfs:
      - <<: *default
        ipv4:
          source_address: 192.0.2.2
          access_list: *default_ipv4_acl
        ipv6:
          source_address: 2001:db8::2
          access_list: *default_ipv6_acl
      - <<: *customer_a
        ipv4:
          source_address: 10.0.0.2
          access_list: *customer_a_ipv4_acl
```
