> For the complete documentation index, see [llms.txt](https://nso-docs.cisco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nso-docs.cisco.com/guides/operation-and-usage/operations/ssh-key-management.md).

# SSH Key Management

Learn about NSO SSH key management.

The SSH protocol uses public key technology for two distinct purposes:

1. **Server Authentication**: This use is a mandatory part of the protocol. It allows an SSH client to authenticate the server, i.e. verify that it is really talking to the intended server and not some man-in-the-middle intruder. This requires that the client has prior knowledge of the server's public keys, and the server proves its possession of one of the corresponding private keys by using it to sign some data. These keys are normally called 'host keys', and the authentication procedure is typically referred to as 'host key verification' or 'host key checking'.
2. **Client Authentication**: This use is one of several possible client authentication methods, i.e. it is an alternative to the commonly used password authentication. The server is configured with one or more public keys which are authorized for authentication of a user. The client proves possession of one of the corresponding private keys by using it to sign some data - i.e. the exact reverse of the server authentication provided by host keys. The method is called 'public key authentication' in SSH terminology.

These two usages are fundamentally independent, i.e., host key verification is done regardless of whether the client authentication is via public key, password, or some other method. However host key verification is of particular importance when client authentication is done via password, since failure to detect a man-in-the-middle attack in this case will result in the cleartext password being divulged to the attacker.

## NSO as SSH Server <a href="#ug.ssh_keys.server" id="ug.ssh_keys.server"></a>

NSO can act as an SSH server for northbound connections to the CLI or the NETCONF agent, and for connections from other nodes in an NSO cluster - cluster connections use NETCONF, and the server side setup used is the same as for northbound connections to the NETCONF agent. It is possible to use either the NSO built-in SSH server or an external server such as OpenSSH, for all of these cases. When using an external SSH server, host keys for server authentication and authorized keys for client/user authentication need to be set up per the documentation for that server, and there is no NSO-specific key management in this case.

When the NSO built-in SSH server is used, the setup is very similar to the one OpenSSH uses:

### Host Keys <a href="#d5e4103" id="d5e4103"></a>

The private host keys must be placed in the directory specified by `/ncs-config/aaa/ssh-server-key-dir` in `ncs.conf`. The built-in SSH server recognizes the following key types and file names:

| Key type                           | Private key file       |
| ---------------------------------- | ---------------------- |
| ED25519                            | `ssh_host_ed25519_key` |
| ECDSA                              | `ssh_host_ecdsa_key`   |
| RSA, including RSA-SHA2 signatures | `ssh_host_rsa_key`     |
| DSA                                | `ssh_host_dsa_key`     |

The private keys must be unencrypted and use a format supported by the Erlang/OTP SSH implementation, such as one generated by the OpenSSH `ssh-keygen` command. Protect the private keys with file-system permissions. NSO does not enforce the permissions. Corresponding public keys are typically stored in the same directory with a `.pub` extension, but NSO does not use them.

A host key is usable only when its corresponding algorithm is enabled under `/ncs-config/ssh/algorithms/server-host-key`.

#### SSH Server Algorithms

The algorithms allowed for the built-in SSH server are configured under `/ncs-config/ssh/algorithms` in `ncs.conf`. Separate settings control the server host-key, key-exchange, MAC, and encryption algorithms. Each setting contains a comma-separated preference list; its order determines the order advertised by the server during negotiation.

The effective algorithm set can be smaller than the configured set. In FIPS mode, an algorithm must also be permitted by the applicable FIPS restrictions. A server host-key algorithm additionally requires a corresponding private key. See [`ncs.conf(5)`](/guides/resources/man/ncs.conf.5.md) for the release-specific defaults and recognized values.

These settings apply only to the NSO built-in SSH server. When an external SSH server such as OpenSSH terminates a connection, configure its algorithms using that server's configuration.

### Public Key Authentication <a href="#d5e4113" id="d5e4113"></a>

The public keys that are authorized for authentication of a given user must be placed in the user's SSH directory. Refer to [Public Key Login](https://nso-docs.cisco.com/guides/operation-and-usage/operations/pages/oUchYxSeOKkwhPOOefVU#ug.aaa.public_key_login) for details on how NSO searches for the keys to use.

## NSO as SSH Client <a href="#ug.ssh_keys.client" id="ug.ssh_keys.client"></a>

NSO can act as an SSH client for connections to managed devices that use SSH (this is always the case for devices accessed via NETCONF, typically also for devices accessed via CLI), and for connections to other nodes in an NSO cluster. The [examples.ncs/aaa/ssh-keys](https://github.com/NSO-developer/nso-examples/tree/6.7/aaa/ssh-keys) example in the NSO example collection has a detailed walk-through of the NSO functionality that is described in this section.

#### SSH Client Implementations

NSO uses different SSH client implementations depending on the connection:

| Connection                                                                                                 | SSH implementation                            |
| ---------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| Built-in NETCONF connection to a managed device, including a Generic or 3PY NED that uses built-in NETCONF | Erlang/OTP SSH                                |
| Connection to another NSO cluster node                                                                     | Erlang/OTP SSH                                |
| Device or cluster `fetch-host-keys` action                                                                 | Erlang/OTP SSH                                |
| NSO device-manager SCP or SFTP operation                                                                   | Erlang/OTP SSH                                |
| Java CLI, Generic, or 3PY NED that uses the NSO `SSHClient` API                                            | The SSHJ version bundled with the NSO release |

A custom NED can use a different SSH implementation. Consult the [NED documentation](https://nso-docs.cisco.com/guides/operation-and-usage/operations/pages/vGfK2qplvC1wu0670OgS#sec.config_device.with.ciscoid) when it does not use the NSO `SSHClient` API.

#### Configuring SSH Client Algorithms

The ordered lists of algorithms allowed for southbound SSH negotiations can be configured in the following locations:

* `/devices/global-settings/ssh-algorithms`
* `/devices/profiles/profile/ssh-algorithms`
* `/devices/device/ssh-algorithms`
* `/devices/device/live-status-protocol/ssh-algorithms`
* `/cluster/remote-node/ssh-algorithms`

For a managed device, a device-specific value takes precedence over a device-profile value, and a device-profile value takes precedence over the global value. A live-status protocol can override the settings inherited from its device. Each algorithm category is resolved independently, so an override of one category does not require repeating the other categories.

NSO filters each configured list to algorithms supported by the SSH client used for the connection, while preserving the configured order. In FIPS mode, the configured algorithms are also subject to the applicable FIPS restrictions. For a public-key algorithm, a compatible key must also be available.

Because `fetch-host-keys` and a subsequent Java NED connection use different SSH implementations, successful host-key retrieval does not prove that SSHJ can negotiate the same algorithms, or vice versa.

{% hint style="warning" %}
The legacy `ssh-rsa` and `ssh-dss` public-key algorithms are not enabled by default. Explicitly enable them only for a peer that does not support a default alternative.

`ssh-rsa` identifies the legacy RSA-with-SHA-1 signature algorithm. Disabling it does not disable RSA keys. The `rsa-sha2-256` and `rsa-sha2-512` algorithms use the same RSA key format with SHA-2 signatures and are configured separately.
{% endhint %}

#### Identifying Negotiated Algorithms

For northbound NETCONF connections using the built-in SSH server, the NETCONF log (normally `netconf.log`), when enabled, records the negotiated key-exchange, host-key, cipher, MAC, and compression algorithms.

For southbound NETCONF connections using the Erlang SSH client, enable device tracing and inspect the applicable `netconf-<device>.trace` file. See Tracing Device Communication. SSHJ makes negotiated connection information available to a Java NED, but whether it appears in a device trace depends on the NED implementation.

Equivalent negotiation logging is not available for every SSH connection type, including northbound CLI connections. NSO does not provide a single command that lists the effective algorithms for all SSH implementations.

### Host Key Verification <a href="#ug.ssh_keys.client.host_keys" id="ug.ssh_keys.client.host_keys"></a>

#### **Verification Level**

The level of host key verification can be set globally via `/ssh/host-key-verification`. The possible values are:

* `reject-unknown`: The host key provided by the device or cluster node must be known by NSO for the connection to succeed.
* `reject-mismatch`: The host key provided by the device or cluster node may be unknown, but it must not be different from the "known" key for the same key algorithm, for the connection to succeed.
* `none`: No host key verification is done - the connection will never fail due to the host key provided by the device or cluster node.

The default is `reject-unknown`, and it is not recommended to use a different value, although it can be useful or needed in certain circumstances. E.g. `none` maybe useful in a development scenario, and temporary use of `reject-mismatch` maybe motivated until host keys have been configured for a set of existing managed devices.

{% code title="Allowing SSH Connections With Unknown Host Keys" %}

```bash
admin@ncs(config)# ssh host-key-verification reject-mismatch
admin@ncs(config)# commit
Commit complete.
```

{% endcode %}

#### **Connection to a Managed Device**

The public host keys for a device that is accessed via SSH are stored in the `/devices/device/ssh/host-key` list. The NSO data model represents the following key formats: `ssh-ed25519`, `ssh-dss`, `ssh-rsa`, `ecdsa-256`, `ecdsa-384`, `ecdsa-521`, and `ssh-ed448`. Whether NSO can retrieve or use a particular key depends on the SSH implementation used for the connection and the active FIPS mode.

If a device has `live-status-protocol` entries that use SSH, their host keys can be stored in `/devices/device/live-status-protocol/ssh/host-key`. If `/devices/device/live-status-protocol/ssh` does not exist, the host keys configured for the device are used for that protocol.

The keys can be configured directly through the CLI, but it is generally preferable to retrieve them using the actions described below. These actions also retrieve the keys for any `live-status-protocol` entries that use SSH.

The level of host key verification can also be set per device, via `/devices/device/ssh/host-key-verification`. The default is to use the global value (or default) for `/ssh/host-key-verification`, but any explicitly set value will override the global value. The possible values are the same as for `/ssh/host-key-verification`.

There are several actions that can be used to retrieve the host keys from a device and store them in the NSO configuration:

* `/devices/fetch-ssh-host-keys`: Retrieve the host keys for all devices. Successfully retrieved keys are committed to the configuration.
* `/devices/device-group/fetch-ssh-host-keys`: Retrieve the host keys for all devices in a device group. Successfully retrieved keys are committed to the configuration.
* `/devices/device/ssh/fetch-host-keys`: Retrieve the host keys for one or more devices. In the CLI, range expressions can be used for the device name, e.g. using '\*' will retrieve keys for all devices, etc. The action will commit the retrieved keys if possible, i.e. if the device entry is already committed, otherwise (i.e., if the action is invoked from "configure mode" when the device entry has been created but not committed), the keys will be written to the current transaction, but not committed.

The actions use the Erlang/OTP SSH client and consider only the configured public-key algorithms supported by that implementation. NSO retrieves one host key for each key format. Signature algorithms that share a format do not produce separate stored keys. For example, `ssh-rsa`, `rsa-sha2-256`, and `rsa-sha2-512` all use the RSA host-key format and result in one `ssh-rsa` entry under `/devices/device/ssh/host-key`.

The fingerprints of the retrieved keys will be reported as part of the result from these actions, but it is also possible to ask for the fingerprints of already retrieved keys by invoking the `/devices/device/ssh/host-key/show-fingerprint` action (`/devices/device/live-status-protocol/ssh/host-key/show-fingerprint` for live-status protocols that use SSH).

{% code title="Retrieving SSH Host Keys for All Configured Devices" %}

```bash
admin@ncs# devices fetch-ssh-host-keys
fetch-result {
    device c0
    result unchanged
    fingerprint {
        algorithm ssh-dss
        value 03:64:fc:b7:87:bd:34:5e:3b:6e:d8:71:4d:3f:46:76
    }
}
fetch-result {
    device h0
    result unchanged
    fingerprint {
        algorithm ssh-dss
        value 03:64:fc:b7:87:bd:34:5e:3b:6e:d8:71:4d:3f:46:76
    }
}
```

{% endcode %}

#### **Connection to an NSO Cluster Node**

This is very similar to the case of a connection to a managed device, it differs mainly in locations - and in the fact that SSH is always used for connection to a cluster node. The public host keys for a cluster node are stored in the `/cluster/remote-node/ssh/host-key` list, in the same way as the host keys for a device. The keys can be configured e.g. via input directly in the CLI, but in most cases, it will be preferable to use the action described below to retrieve keys from the cluster node.

The level of host key verification can also be set per cluster node, via `/cluster/remote-node/ssh/host-key-verification`. The default is to use the global value (or default) for `/ssh/host-key-verification`, but any explicitly set value will override the global value. The possible values are the same as for `/ssh/host-key-verification`.

The `/cluster/remote-node/ssh/fetch-host-keys` action can be used to retrieve the host keys for one or more cluster nodes. In the CLI, range expressions can be used for the node name, e.g. using '\*' will retrieve keys for all nodes, etc. The action will commit the retrieved keys if possible, but if it is invoked from "configure mode" when the node entry has been created but not committed, the keys will be written to the current transaction, but not committed.

The fingerprints of the retrieved keys will be reported as part of the result from this action, but it is also possible to ask for the fingerprints of already retrieved keys by invoking the `/cluster/remote-node/ssh/host-key/show-fingerprint` action.

{% code title="Retrieving SSH Host Keys for All Cluster Nodes" %}

```bash
admin@ncs# cluster remote-node * ssh fetch-host-keys
cluster remote-node ncs1 ssh fetch-host-keys
    result updated
    fingerprint {
        algorithm ssh-dss
        value 03:64:fc:b7:87:bd:34:5e:3b:6e:d8:71:4d:3f:46:76
    }
cluster remote-node ncs2 ssh fetch-host-keys
    result updated
    fingerprint {
        algorithm ssh-dss
        value 03:64:fc:b7:87:bd:34:5e:3b:6e:d8:71:4d:3f:46:76
    }
cluster remote-node ncs3 ssh fetch-host-keys
    result updated
    fingerprint {
        algorithm ssh-dss
        value 03:64:fc:b7:87:bd:34:5e:3b:6e:d8:71:4d:3f:46:76
    }
```

{% endcode %}

### Public Key Authentication

#### **Private Key Selection**

The private key used for public key authentication can be taken either from the SSH directory for the local user or from a list of private keys in the NSO configuration. The user's SSH directory is determined according to the same logic as for the server-side public keys that are authorized for authentication of a given user, see [Public Key Login](https://nso-docs.cisco.com/guides/operation-and-usage/operations/pages/oUchYxSeOKkwhPOOefVU#ug.aaa.public_key_login), but of course, different files in this directory are used, see below. Alternatively, the key can be configured in the `/ssh/private-key` list, using an arbitrary name for the list key. In both cases, the key must be in PEM format (e.g. as generated by the OpenSSH **ssh-keygen** command), and it may be encrypted or not. Encrypted keys configured in `/ssh/private-key` must have the passphrase for the key configured via `/ssh/private-key/passphrase`.

#### **Connection to a Managed Device**

The specific private key to use is configured via the `authgroup` indirection and the `umap` selection mechanisms as for password authentication, just a different alternative. Setting `/devices/authgroups/group/umap/public-key` (or `default-map` instead of `umap` for users that are not in `umap`) without any additional parameters will select the default of using a file called `id_dsa` in the local user's SSH directory, which must have an unencrypted key. A different file name can be set via `/devices/authgroups/group/umap/public-key/private-key/file/name`. For an encrypted key, the passphrase can be set via `/devices/authgroups/group/umap/public-key/private-key/file/passphrase`, or `/devices/authgroups/group/umap/public-key/private-key/file/use-password` can be set to indicate that the password used (if any) by the local user when authenticating to NSO should also be used as a passphrase for the key. To instead select a private key from the `/ssh/private-key` list, the name of the key is set via `/devices/authgroups/group/umap/public-key/private-key/name`.

{% code title="Configuring a Private Key File for Publickey Authentication to Devices" %}

```bash
admin@ncs(config)# devices authgroups group default umap admin
admin@ncs(config-umap-admin)# public-key private-key file name /home/admin/.ssh/id-dsa
admin@ncs(config-umap-admin)# public-key private-key file passphrase
(<AES encrypted string>): *********
admin@ncs(config-umap-admin)# commit
Commit complete.
```

{% endcode %}

#### **Connection to an NSO Cluster Node**

This is again very similar to the case of a connection to a managed device, since the same `authgroup`/`umap` scheme is used. Setting `/cluster/authgroup/umap/public-key` (or `default-map` instead of `umap` for users that are not in `umap`) without any additional parameters will select the default of using a file called `id_dsa` in the local user's SSH directory, which must have an unencrypted key. A different file name can be set via `/cluster/authgroup/umap/public-key/private-key/file/name`. For an encrypted key, the passphrase can be set via `/cluster/authgroup/umap/public-key/private-key/file/passphrase`, or `/cluster/authgroup/umap/public-key/private-key/file/use-password` can be set to indicate that the password used (if any) by the local user when authenticating to NSO should also be used as a passphrase for the key. To instead select a private key from the `/ssh/private-key` list, the name of the key is set via `/cluster/authgroup/umap/public-key/private-key/name`.

{% code title="Configuring a Private Key File for Publickey Authentication in Cluster" %}

```bash
admin@ncs(config)# cluster authgroup default umap admin
admin@ncs(config-umap-admin)# public-key private-key file name /home/admin/.ssh/id-dsa
admin@ncs(config-umap-admin)# public-key private-key file passphrase
(<AES encrypted string>): *********
admin@ncs(config-umap-admin)# commit
Commit complete.
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://nso-docs.cisco.com/guides/operation-and-usage/operations/ssh-key-management.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
