Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions administration/advanced-topics/ipc-connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,26 @@ description: Connect client libraries to NSO with IPC.

# IPC Connection

Client libraries connect to NSO for inter-process communication (IPC) using TCP or Unix domain sockets.
Client libraries connect to NSO for inter-process communication (IPC) using Unix domain sockets (Local IPC) or TCP. By default, NSO uses Local IPC over a Unix domain socket at the path `/tmp/nso/nso-ipc`, controlled by the `/ncs-config/ncs-local-ipc/path` element in `ncs.conf`. If you change the socket path, you can tell clients to use the new path through the `NCS_IPC_PATH` environment variable. Clients must also have filesystem permission to access the IPC socket path, or they will not be able to communicate with the NSO daemon process. Local IPC requires clients to run on the same host as NSO; for clients running on a remote host, use TCP IPC instead.

If NSO is configured to use TCP sockets for IPC, you can tell NSO which address to use for these connections through the `/ncs-config/ncs-ipc-address/ip` (default value 127.0.0.1) and `/ncs-config/ncs-ipc-address/port` (default value 4569) elements in `ncs.conf`. If you change these values, you will likely need to configure the clients accordingly. Note that these values have security implications; see [Security Issues](../installation-and-deployment/deployment/secure-deployment.md#securing-ipc-access). In particular, changing the address away from 127.0.0.1 may allow unauthenticated remote connections.
Alternatively, NSO can be configured to use TCP sockets for IPC by setting `/ncs-config/ncs-local-ipc/enabled` to `false` and configuring the address and port through the `/ncs-config/ncs-ipc-address/ip` (default value 127.0.0.1) and `/ncs-config/ncs-ipc-address/port` elements in `ncs.conf`. If you change these values, you will likely need to configure the clients accordingly. Note that these values have security implications; see [Security Issues](../installation-and-deployment/deployment/secure-deployment.md#securing-ipc-access). In particular, changing the address away from 127.0.0.1 may allow unauthenticated remote connections.

Many of the clients read the environment variables `NCS_IPC_ADDR` and `NCS_IPC_PORT` to determine if something other than the default is to be used, but others might need source code changes. This is a list of clients that communicate with NSO and what needs to be done when `ncs-ipc-address` is changed.
Many of the clients read the environment variable `NCS_IPC_PATH` to determine the Local IPC socket path, or `NCS_IPC_ADDR` and `NCS_IPC_PORT` for TCP IPC, but others might need source code changes. When both `NCS_IPC_PATH` and `NCS_IPC_PORT` are set, `NCS_IPC_PATH` takes precedence and TCP is not used. This is a list of clients that communicate with NSO and what needs to be done when the IPC configuration is changed.

<table><thead><tr><th width="218">Client</th><th>Changes required</th></tr></thead><tbody><tr><td>Remote commands via the <code>ncs</code> command</td><td>Remote commands, such as <code>ncs --reload</code>, check the environment variables <code>NCS_IPC_ADDR</code> and <code>NCS_IPC_PORT</code>.</td></tr><tr><td>CLI tools</td><td>The Command Line Interface (CLI) client <strong>ncs_cli</strong> and similar commands, such as <code>ncs_cmd</code> and <code>ncs_load</code>, check the environment variables <code>NCS_IPC_ADDR</code> and <code>NCS_IPC_PORT</code>. Alternatively, many of them also support command-line options.</td></tr><tr><td>CDB and MAAPI clients</td><td>The address supplied to <code>Cdb.connect()</code> and <code>Maapi.connect()</code> must be changed.</td></tr><tr><td>Data provider API clients</td><td>The address supplied to <code>Dp</code> constructor socket must be changed.</td></tr><tr><td>Notification API clients</td><td>The new address must be supplied to the socket for the <code>Nofif</code> constructor.</td></tr></tbody></table>
<table><thead><tr><th width="218">Client</th><th>Changes required</th></tr></thead><tbody><tr><td>Remote commands via the <code>ncs</code> command</td><td>Remote commands, such as <code>ncs --reload</code>, check the environment variables <code>NCS_IPC_PATH</code> and <code>NCS_IPC_ADDR</code>/<code>NCS_IPC_PORT</code>.</td></tr><tr><td>CLI tools</td><td>The Command Line Interface (CLI) client <strong>ncs_cli</strong> and similar commands, such as <code>ncs_cmd</code> and <code>ncs_load</code>, check the environment variables <code>NCS_IPC_PATH</code> and <code>NCS_IPC_ADDR</code>/<code>NCS_IPC_PORT</code>. Alternatively, many of them also support command-line options (e.g. <code>-S</code> for socket path).</td></tr><tr><td>CDB and MAAPI clients</td><td>The address or path supplied to <code>Cdb.connect()</code> and <code>Maapi.connect()</code> must be changed.</td></tr><tr><td>Data provider API clients</td><td>The address or path supplied to <code>Dp</code> constructor socket must be changed.</td></tr><tr><td>Notification API clients</td><td>The new address or path must be supplied to the socket for the <code>Notif</code> constructor.</td></tr></tbody></table>

Likewise, if NSO is configured to use Unix domain sockets for IPC and you have changed the path under `/ncs-config/ncs-local-ipc/path` in `ncs.conf`, you can tell clients to use the new path through the `NCS_IPC_PATH` environment variable. Clients must also have filesystem permission to access the IPC path, or they will not be able to communicate with the NSO daemon process.

To run more than one instance of NSO on the same host (which can be useful in development scenarios), each instance needs its own IPC socket. If using TCP for IPC, set `/ncs-config/ncs-ipc-address/port` in `ncs.conf` to different values for each instance. If, instead, you are using Unix sockets for IPC, set `/ncs-config/ncs-local-ipc/path` in `ncs.conf` to different values. In either case, you may also need to change the NETCONF and CLI over SSH ports under `/ncs-config/netconf/transport` and `/ncs-config/cli/ssh` by either disabling them or changing their values.
To run more than one instance of NSO on the same host (which can be useful in development scenarios), each instance needs its own IPC socket. Set `/ncs-config/ncs-local-ipc/path` in `ncs.conf` to different values for each instance. If, instead, you are using TCP for IPC, set `/ncs-config/ncs-ipc-address/port` in `ncs.conf` to different values. In either case, you may also need to change the NETCONF and CLI over SSH ports under `/ncs-config/netconf/transport` and `/ncs-config/cli/ssh` by either disabling them or changing their values.

## Restricting Access to the IPC Socket

By default, clients connecting to the IPC socket are considered trusted, i.e., there is no authentication required, as the system relies on the use of 127.0.0.1 for `/ncs-config/ncs-ipc-address/ip` or Unix domain sockets to prevent remote access. In case this is not sufficient, such as when untrusted users have shell access on the system where NSO runs, it is possible to further restrict the access to the IPC socket.
By default, clients connecting to the IPC socket are considered trusted, i.e., there is no authentication required. Since NSO uses Local IPC by default, the system relies on Unix filesystem permissions on the socket path to prevent unauthorized access. In case this is not sufficient, such as when untrusted users have shell access on the system where NSO runs, it is possible to further restrict the access to the IPC socket.

If Unix domain sockets are used, you can leverage Unix filesystem permissions for the socket path to limit which OS users and groups can initiate connections to the socket. NSO may also perform additional authentication of the connecting users; see [Authenticating IPC Access](../management/aaa-infrastructure.md#authenticating-ipc-access).
When using Unix domain sockets (Local IPC), you can leverage Unix filesystem permissions for the socket path to limit which OS users and groups can initiate connections to the socket. NSO may also perform additional authentication of the connecting users based on their UID; see [Authenticating IPC Access](../management/aaa-infrastructure.md#authenticating-ipc-access).

For TCP sockets, you can enable an access check by setting the `ncs.conf` element `/ncs-config/ncs-ipc-access-check/enabled` to `true`, and specifying a filename for `/ncs-config/ncs-ipc-access-check/filename`. The file should contain a shared secret, i.e., a random (printable ASCII) character string. Clients connecting to the IPC socket will then be required to prove that they have knowledge of the secret through a challenge handshake before they are allowed access to the NSO functions provided via the IPC socket.

{% hint style="info" %}
The access permissions on this file must be restricted via OS file permissions, such that it can only be read by the NSO daemon and client processes that are allowed to connect to the IPC port. E.g. if both the daemon and the clients run as root, the file can be owned by root and have only "read by owner" permission (i.e. mode 0400). Another possibility is to have a group that only the daemon and the clients belong to, set the group ID of the file to that group, and have only "read by group" permission (i.e. mode 040).
The access permissions on this file must be restricted via OS file permissions, such that it can only be read by the NSO daemon and client processes that are allowed to connect to the IPC socket. E.g. if both the daemon and the clients run as root, the file can be owned by root and have only "read by owner" permission (i.e. mode 0400). Another possibility is to have a group that only the daemon and the clients belong to, set the group ID of the file to that group, and have only "read by group" permission (i.e. mode 040).
{% endhint %}

To provide the secret to the client libraries and inform them that they need to use the access check handshake, you have to set the environment variable `NCS_IPC_ACCESS_FILE` to the full pathname of the file containing the secret. This is sufficient for all the clients mentioned above, i.e., there is no need to change the application code to support or enable this check.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ The default `aaa_init.xml` file must not be used as-is before reviewing and veri

For a detailed discussion of the configuration of authorization rules through NACM, see [AAA infrastructure](../../management/aaa-infrastructure.md), particularly the section [Authorization](../../management/aaa-infrastructure.md#ug.aaa.authorization).

A considerably more complex scenario is when users require shell access to the host but are either untrusted or should not have any access to NSO at all. NSO listens to a so-called IPC socket configured through `/ncs-config/ncs-ipc-address`. This socket is typically limited to local connections and defaults to `127.0.0.1:4569` for security. The socket multiplexes several different access methods to NSO.
A considerably more complex scenario is when users require shell access to the host but are either untrusted or should not have any access to NSO at all. NSO listens on an IPC socket, which by default is a Unix domain socket (Local IPC) configured through `/ncs-config/ncs-local-ipc`. Alternatively, NSO can be configured to use a TCP socket through `/ncs-config/ncs-ipc-address`. In either case, the socket is typically limited to local connections for security. The socket multiplexes several different access methods to NSO.

The main security-related point is that no AAA checks are performed on this socket. If you have access to the socket, you also have complete access to all of NSO.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Examples of programs that connect using IPC sockets:
### Default Security

* Only local connections to IPC sockets are allowed by default.
* TCP sockets with no authentication.
* Unix domain sockets (Local IPC) are used by default, relying on filesystem permissions for access control.

### Best Practices

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ You already have another instance of NSO running (or the same with netsim):

```bash
$ ncs
Cannot bind to internal socket 127.0.0.1:4569 : address already in use
Cannot bind to internal socket /tmp/nso/nso-ipc : address already in use
Daemon died status=20
$ ncs-netsim start
DEVICE c0 Cannot bind to internal socket 127.0.0.1:5010 : \
Expand Down
6 changes: 3 additions & 3 deletions administration/management/aaa-infrastructure.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,11 @@ The same is possible for the group. This unauthenticated access is currently the

The main condition here is that all clients connecting to the socket are trusted to use the correct user and group information. That is often not the case, such as untrusted users having shell access to the host to run `ncs_cli` or otherwise initiate local connections to the IPC socket. Then access to the socket must be restricted.

In general, authenticating access to the IPC socket is a security best practice and should always be used. When NSO is configured to use Unix domain sockets for IPC, it authenticates the client based on the UID of the other end of the socket connection. Alternatively, the system can be instructed to use TCP sockets. In this case, the system should be configured to use an access check, where every IPC client must prove that it has access to a pre-shared key. See [Restricting Access to the IPC Socket](../advanced-topics/ipc-connection.md#restricting-access-to-the-ipc-socket) on how to enable it.
In general, authenticating access to the IPC socket is a security best practice and should always be used. NSO uses Unix domain sockets for IPC by default, and authenticates the client based on the UID of the other end of the socket connection. Alternatively, the system can be configured to use TCP sockets. In this case, the system should be configured to use an access check, where every IPC client must prove that it has access to a pre-shared key. See [Restricting Access to the IPC Socket](../advanced-topics/ipc-connection.md#restricting-access-to-the-ipc-socket) on how to enable it.

### UID-based Authentication for Unix Sockets

NSO will use Unix domain sockets for IPC communications when `ncs-local-ipc/enabled` configuration in `ncs.conf` is set to true. The main benefit of this communication method is that it is generally more secure than TCP sockets. It also provides additional information on the communicating peer, such as the user ID of the calling process. NSO can then use this information to authenticate the peer.
NSO uses Unix domain sockets for IPC communications by default (the `ncs-local-ipc/enabled` configuration in `ncs.conf` defaults to `true`). The main benefit of this communication method is that it is generally more secure than TCP sockets. It also provides additional information on the communicating peer, such as the user ID of the calling process. NSO can then use this information to authenticate the peer.

As part of the initial handshake, NSO reads the effective UID (euid) of the process initiating the Unix socket connection. The system then finds an `/aaa/authentication/users/user` entry with the corresponding `uid` value. Access is permitted or denied based on the `local_ipc_access` value. If access is permitted, the user connects as the user, found in the `/aaa/authentication/users/user` list. The following is an example of such a user list entry:

Expand All @@ -669,7 +669,7 @@ aaa authentication users user admin

NSO will skip this access check in case the euid of the connecting process is 0 (root user) or same as the user NSO is running as. (In both these cases, the connecting user could access NSO data directly, bypassing the access check.)

If using Unix socket IPC, clients and client libraries must now specify the path that identifies the socket. The path must match the one set under `ncs-local-ipc/path` in `ncs.conf`. Clients may expose a client-specific way to set it, such as the `-S` option of the `ncs_cli` command. Alternatively, you can use the `NCS_IPC_PATH` environment variable to specify the socket path independently of the used client.
If the default Local IPC socket path has been changed, clients and client libraries must specify the path that identifies the socket. The path must match the one set under `ncs-local-ipc/path` in `ncs.conf`. Clients may expose a client-specific way to set it, such as the `-S` option of the `ncs_cli` command. Alternatively, you can use the `NCS_IPC_PATH` environment variable to specify the socket path independently of the used client.

See [examples.ncs/aaa/ipc](https://github.com/NSO-developer/nso-examples/tree/6.6/aaa/ipc) for a working example.

Expand Down
2 changes: 1 addition & 1 deletion administration/management/system-management/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ In this section, some of the important configuration settings will be described

### Exposed Interfaces

NSO allows access through a number of different interfaces, depending on the use case. In the default configuration, clients can access the system locally through an unauthenticated IPC socket (with the `ncs*` family of commands, port 4569) and plain (non-HTTPS) HTTP web server (port 8080). Additionally, the system enables remote access through SSH-secured NETCONF and CLI (ports 2022 and 2024).
NSO allows access through a number of different interfaces, depending on the use case. In the default configuration, clients can access the system locally through an unauthenticated IPC socket (with the `ncs*` family of commands, using Local IPC over a Unix domain socket) and plain (non-HTTPS) HTTP web server (port 8080). Additionally, the system enables remote access through SSH-secured NETCONF and CLI (ports 2022 and 2024).

We strongly encourage you to review and customize the exposed interfaces to your needs in the `ncs.conf` configuration file. In particular, set:

Expand Down
4 changes: 2 additions & 2 deletions developer-reference/pyapi/_ncs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2113,8 +2113,8 @@ NCS_PORT = 4569
NO_DB = 0
OK = 0
OPERATIONAL = 4
PATH = None
PORT = 4569
PATH = '/tmp/nso/nso-ipc'
PORT = None
PRE_COMMIT_RUNNING = 6
PROGRESS_INFO = 3
PROGRESS_START = 1
Expand Down
6 changes: 3 additions & 3 deletions developer-reference/pyapi/ncs.cdb.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Use this class when subscribing on operational data. In all other means
the behavior is the same as for Subscriber().

```python
OperSubscriber(app=None, log=None, host='127.0.0.1', port=4569, path=None)
OperSubscriber(app=None, log=None, host='127.0.0.1', port=None, path='/tmp/nso/nso-ipc')
```

Initialize an OperSubscriber.
Expand Down Expand Up @@ -369,7 +369,7 @@ calls for all subscription points, and finally a single call to
post_iterate().

```python
Subscriber(app=None, log=None, host='127.0.0.1', port=4569, subtype=1, name='', path=None)
Subscriber(app=None, log=None, host='127.0.0.1', port=None, subtype=1, name='', path='/tmp/nso/nso-ipc')
```

Initialize a Subscriber.
Expand Down Expand Up @@ -692,7 +692,7 @@ Methods are called in the following order:
3. should_iterate -> abort, if transaction is aborted by other subscriber

```python
TwoPhaseSubscriber(name, app=None, log=None, host='127.0.0.1', port=4569, path=None)
TwoPhaseSubscriber(name, app=None, log=None, host='127.0.0.1', port=None, path='/tmp/nso/nso-ipc')
```

Members:
Expand Down
2 changes: 1 addition & 1 deletion developer-reference/pyapi/ncs.dp.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Custom actionpoint stop triggered when Python VM shuts down.
Manage a data provider connection towards ConfD/NCS.

```python
Daemon(name, log=None, ip='127.0.0.1', port=4569, path=None, state_mgr=None)
Daemon(name, log=None, ip='127.0.0.1', port=None, path='/tmp/nso/nso-ipc', state_mgr=None)
```

Initialize a Daemon object.
Expand Down
Loading