Manage user authentication, authorization, and audit using NSO's AAA mechanism.
Users log into NSO through the CLI, NETCONF, RESTCONF, SNMP, or via the Web UI. In either case, users need to be authenticated. That is, a user needs to present credentials, such as a password or a public key to gain access. As an alternative, for RESTCONF, users can be authenticated via token validation.
Once a user is authenticated, all operations performed by that user need to be authorized. That is, certain users may be allowed to perform certain tasks, whereas others are not. This is called authorization. We differentiate between the authorization of commands and the authorization of data access.
The NSO daemon manages device configuration including AAA information. NSO manages AAA information as well as uses it. The AAA information describes which users may log in, what passwords they have, and what they are allowed to do. This is solved in NSO by requiring a data model to be both loaded and populated with data. NSO uses the YANG module tailf-aaa.yang
for authentication, while ietf-netconf-acm.yang
(NETCONF Access Control Model (NACM), RFC 8341) as augmented by tailf-acm.yang
is used for group assignment and authorization.
The NACM data model is targeted specifically towards access control for NETCONF operations and thus lacks some functionality that is needed in NSO, in particular, support for the authorization of CLI commands and the possibility to specify the context (NETCONF, CLI, etc.) that a given authorization rule should apply to. This functionality is modeled by augmentation of the NACM model, as defined in the tailf-acm.yang
YANG module.
The ietf-netconf-acm.yang
and tailf-acm.yang
modules can be found in $NCS_DIR/src/ncs/yang
directory in the release, while tailf-aaa.yang
can be found in the $NCS_DIR/src/ncs/aaa
directory.
NACM options related to services are modeled by augmentation of the NACM model, as defined in the tailf-ncs-acm.yang
YANG module. The tailf-ncs-acm.yang
can be found in $NCS_DIR/src/ncs/yang
directory in the release.
The complete AAA data model defines a set of users, a set of groups, and a set of rules. The data model must be populated with data that is subsequently used by by NSO itself when it authenticates users and authorizes user data access. These YANG modules work exactly like all other fxs
files loaded into the system with the exception that NSO itself uses them. The data belongs to the application, but NSO itself is the user of the data.
Since NSO requires a data model for the AAA information for its operation, it will report an error and fail to start if these data models cannot be found.
ncs.conf
NSO itself is configured through a configuration file - ncs.conf
. In that file, we have the following items related to authentication and authorization:
/ncs-config/aaa/ssh-server-key-dir
: If SSH termination is enabled for NETCONF or the CLI, the NSO built-in SSH server needs to have server keys. These keys are generated by the NSO install script and by default end up in $NCS_DIR/etc/ncs/ssh
.
It is also possible to use OpenSSH to terminate NETCONF or the CLI. If OpenSSH is used to terminate SSH traffic, this setting has no effect.
/ncs-config/aaa/ssh-pubkey-authentication
: If SSH termination is enabled for NETCONF or the CLI, this item controls how the NSO SSH daemon locates the user keys for public key authentication. See Public Key Login for details.
/ncs-config/aaa/local-authentication/enabled
: The term 'local user' refers to a user stored under /aaa/authentication/users
. The alternative is a user unknown to NSO, typically authenticated by PAM. By default, NSO first checks local users before trying PAM or external authentication.
Local authentication is practical in test environments. It is also useful when we want to have one set of users that are allowed to log in to the host with normal shell access and another set of users that are only allowed to access the system using the normal encrypted, fully authenticated, northbound interfaces of NSO.
If we always authenticate users through PAM, it may make sense to set this configurable to false
. If we disable local authentication, it implicitly means that we must use either PAM authentication or external authentication. It also means that we can leave the entire data trees under /aaa/authentication/users
and, in the case of external authentication, also /nacm/groups
(for NACM) or /aaa/authentication/groups
(for legacy tailf-aaa) empty.
/ncs-config/aaa/pam
: NSO can authenticate users using PAM (Pluggable Authentication Modules). PAM is an integral part of most Unix-like systems.
PAM is a complicated - albeit powerful - subsystem. It may be easier to have all users stored locally on the host, However, if we want to store users in a central location, PAM can be used to access the remote information. PAM can be configured to perform most login scenarios including RADIUS and LDAP. One major drawback with PAM authentication is that there is no easy way to extract the group information from PAM. PAM authenticates users, it does not also assign a user to a set of groups. PAM authentication is thoroughly described later in this chapter.
/ncs-config/aaa/default-group
: If this configuration parameter is defined and if the group of a user cannot be determined, a logged-in user ends up in the given default group.
/ncs-config/aaa/external-authentication
: NSO can authenticate users using an external executable. This is further described later in External Authentication. As an alternative, you may consider using package authentication.
/ncs-config/aaa/external-validation
: NSO can authenticate users by validation of tokens using an external executable. This is further described later in External Token Validation. Where external authentication uses a username and password to authenticate a user, external validation uses a token. The validation script should use the token to authenticate a user and can, optionally, also return a new token to be returned with the result of the request. It is currently only supported for RESTCONF.
/ncs-config/aaa/external-challenge
: NSO has support for multi-factor authentication by sending challenges to a user. Challenges may be sent from any of the external authentication mechanisms but are currently only supported by JSON-RPC and CLI over SSH. This is further described later in External Multi-factor Authentication.
/ncs-config/aaa/package-authentication
: NSO can authenticate users using package authentication. It extends the concept of external authentication by allowing multiple packages to be used for authentication instead of a single executable. This is further described in Package Authentication.
/ncs-config/aaa/single-sign-on
: With this setting enabled, NSO invokes Package Authentication on all requests to HTTP endpoints with the /sso
prefix. This way, Package Authentication packages that require custom endpoints can expose them under the /sso
base route.
For example, a SAMLv2 Single Sign-On (SSO) package needs to process requests to an AssertionConsumerService endpoint, such as /sso/saml/acs
, and therefore requires enabling this setting.
This is a valid authentication method for WEB UI and JSON-RPC interfaces and needs Package Authentication to be enabled as well.
/ncs-config/aaa/single-sign-on/enable-automatic-redirect
: If only one Single Sign-On package is configured (a package with single-sign-on-url
set in package-meta-data.xml
) and also this setting is enabled, NSO automatically redirects all unauthenticated access attempts to the configured single-sign-on-url
.
Depending on the northbound management protocol, when a user session is created in NSO, it may or may not be authenticated. If the session is not yet authenticated, NSO's AAA subsystem is used to perform authentication and authorization, as described below. If the session already has been authenticated, NSO's AAA assigns groups to the user as described in Group Membership, and performs authorization, as described in Authorization.
The authentication part of the data model can be found in tailf-aaa.yang
:
AAA authentication is used in the following cases:
When the built-in SSH server is used for NETCONF and CLI sessions.
For Web UI sessions and REST access.
When the method Maapi.Authenticate()
is used.
NSO's AAA authentication is not used in the following cases:
When NETCONF uses an external SSH daemon, such as OpenSSH.
In this case, the NETCONF session is initiated using the program netconf-subsys
, as described in NETCONF Transport Protocols in Northbound APIs.
When NETCONF uses TCP, as described in NETCONF Transport Protocols in Northbound APIs, e.g. through the command netconf-console
.
When accessing the CLI by invoking the ncs_cli
, e.g. through an external SSH daemon, such as OpenSSH, or a telnet daemon.
An important special case here is when a user has shell access to the host and runs ncs_cli from the shell. This command, as well as direct access to the IPC socket, allows for authentication bypass. It is crucial to consider this case for your deployment. If non-trusted users have shell access to the host, IPC access must be restricted. See Authenticating IPC Access.
When SNMP is used, SNMP has its own authentication mechanisms. See NSO SNMP Agent in Northbound APIs.
When the method Maapi.startUserSession()
is used without a preceding call of Maapi.authenticate()
.
When a user logs in over NETCONF or the CLI using the built-in SSH server, with a public key login, the procedure is as follows.
The user presents a username in accordance with the SSH protocol. The SSH server consults the settings for /ncs-config/aaa/ssh-pubkey-authentication
and /ncs-config/aaa/local-authentication/enabled
.
If ssh-pubkey-authentication
is set to local
, and the SSH keys in /aaa/authentication/users/user{$USER}/ssh_keydir
match the keys presented by the user, authentication succeeds.
Otherwise, if ssh-pubkey-authentication
is set to system
, local-authentication
is enabled, and the SSH keys in /aaa/authentication/users/user{$USER}/ssh_keydir
match the keys presented by the user, authentication succeeds.
Otherwise, if ssh-pubkey-authentication
is set to system
and the user /aaa/authentication/users/user{$USER}
does not exist, but the user does exist in the OS password database, the keys in the user's $HOME/.ssh
directory are checked. If these keys match the keys presented by the user, authentication succeeds.
Otherwise, authentication fails.
In all cases the keys are expected to be stored in a file called authorized_keys
(or authorized_keys2
if authorized_keys
does not exist), and in the native OpenSSH format (i.e. as generated by the OpenSSH ssh-keygen
command). If authentication succeeds, the user's group membership is established as described in Group Membership.
This is exactly the same procedure that is used by the OpenSSH server with the exception that the built-in SSH server also may locate the directory containing the public keys for a specific user by consulting the /aaa/authentication/users
tree.
We need to provide a directory where SSH keys are kept for a specific user and give the absolute path to this directory for the /aaa/authentication/users/user/ssh_keydir
leaf. If a public key login is not desired at all for a user, the value of the ssh_keydir
leaf should be set to ""
, i.e. the empty string. Similarly, if the directory does not contain any SSH keys, public key logins for that user will be disabled.
The built-in SSH daemon supports DSA, RSA, and ED25519 keys. To generate and enable RSA keys of size 4096 bits for, say, user "bob", the following steps are required.
On the client machine, as user "bob", generate a private/public key pair as:
Now we need to copy the public key to the target machine where the NETCONF or CLI SSH client runs.
Assume we have the following user entry:
We need to copy the newly generated file id_rsa.pub
, which is the public key, to a file on the target machine called /var/system/users/bob/.ssh/authorized_keys
.
Since the release of OpenSSH 7.0, support of ssh-dss
host and user keys is disabled by default. If you want to continue using these, you may re-enable it using the following options for OpenSSH client:
You can find full instructions at OpenSSH Legacy Options webpage.
Password login is triggered in the following cases:
When a user logs in over NETCONF or the CLI using the built-in SSH server, with a password. The user presents a username and a password in accordance with the SSH protocol.
When a user logs in using the Web UI. The Web UI asks for a username and password.
When the method Maapi.authenticate()
is used.
In this case, NSO will by default try local authentication, PAM, external authentication, and package authentication in that order, as described below. It is possible to change the order in which these are tried, by modifying the ncs.conf
. parameter /ncs-config/aaa/auth-order
. See ncs.conf(5) in Manual Pages for details.
If /aaa/authentication/users/user{$USER}
exists and the presented password matches the encrypted password in /aaa/authentication/users/user{$USER}/password
, the user is authenticated.
If the password does not match or if the user does not exist in /aaa/authentication/users
, PAM login is attempted, if enabled. See PAM for details.
If all of the above fails and external authentication is enabled, the configured executable is invoked. See External Authentication for details.
If authentication succeeds, the user's group membership is established as described in Group Membership.
On operating systems supporting PAM, NSO also supports PAM authentication. Using PAM, authentication with NSO can be very convenient since it allows us to have the same set of users and groups having access to NSO as those that have access to the UNIX/Linux host itself.
PAM is the recommended way to authenticate NSO users.
If we use PAM, we do not have to have any users or any groups configured in the NSO aaa namespace at all.
To configure PAM we typically need to do the following:
Remove all users and groups from the AAA initialization XML file.
Enable PAM in ncs.conf
by adding the following to the AAA section in ncs.conf
. The service
name specifies the PAM service, typically a file in the directory /etc/pam.d
, but may alternatively, be an entry in a file /etc/pam.conf
depending on OS and version. Thus, it is possible to have a different login procedure for NSO than for the host itself.
If PAM is enabled and we want to use PAM for login, the system may have to run as root
. This depends on how PAM is configured locally. However, the default system authentication will typically require root
, since the PAM libraries then read /etc/shadow
. If we don't want to run NSO as root, the solution here is to change the owner of a helper program called $NCS_DIR/lib/ncs/lib/core/pam/priv/epam
and also set the setuid
bit.
As an example, say that we have a user test in /etc/passwd
, and furthermore:
Thus, the test
user is part of the admin
and the operator
groups and logging in to NSO as the test
user through CLI SSH, Web UI, or NETCONF, renders the following in the audit log.
Thus, the test
user was found and authenticated from /etc/passwd
, and the crucial group assignment of the test user was done from /etc/group
.
If we wish to be able to also manipulate the users, their passwords, etc on the device, we can write a private YANG model for that data, store that data in CDB, set up a normal CDB subscriber for that data, and finally when our private user data is manipulated, our CDB subscriber picks up the changes and changes the contents of the relevant /etc
files.
A common situation is when we wish to have all authentication data stored remotely, not locally, for example on a remote RADIUS or LDAP server. This remote authentication server typically not only stores the users and their passwords but also the group information.
If we wish to have not only the users but also the group information stored on a remote server, the best option for NSO authentication is to use external authentication.
If this feature is configured, NSO will invoke the executable configured in /ncs-config/aaa/external-authentication/executable
in ncs.conf
, and pass the username and the clear text password on stdin
using the string notation: "[user;password;]\n"
.
For example, if the user bob
attempts to log in over SSH using the password 'secret', and external authentication is enabled, NSO will invoke the configured executable and write "[bob;secret;]\n"
on the stdin
stream for the executable. The task of the executable is then to authenticate the user and also establish the username-to-groups mapping.
For example, the executable could be a RADIUS client which utilizes some proprietary vendor attributes to retrieve the groups of the user from the RADIUS server. If authentication is successful, the program should write accept
followed by a space-separated list of groups that the user is a member of, and additional information as described below. Again, assuming that bob's password indeed was 'secret', and that bob is a member of the admin
and the lamers
groups, the program should write accept admin lamers $uid $gid $supplementary_gids $HOME
on its standard output and then exit.
There is a general limit of 16000 bytes of output from the externalauth
program.
Thus, the format of the output from an externalauth
program when authentication is successful should be:
"accept $groups $uid $gid $supplementary_gids $HOME\n"
Where:
$groups
is a space-separated list of the group names the user is a member of.
$uid
is the UNIX integer user ID that NSO should use as a default when executing commands for this user.
$gid
is the UNIX integer group ID that NSO should use as a default when executing commands for this user.
$supplementary_gids
is a (possibly empty) space-separated list of additional UNIX group IDs the user is also a member of.
$HOME
is the directory that should be used as HOME for this user when NSO executes commands on behalf of this user.
It is further possible for the program to return a token on successful authentication, by using "accept_token"
instead of "accept"
:
"accept_token $groups $uid $gid $supplementary_gids $HOME $token\n"
Where:
$token
is an arbitrary string. NSO will then, for some northbound interfaces, include this token in responses.
It is also possible for the program to return additional information on successful authentication, by using "accept_info"
instead of "accept"
:
"accept_info $groups $uid $gid $supplementary_gids $HOME $info\n"
Where:
$info
is some arbitrary text. NSO will then just append this text to the generated audit log message (CONFD_EXT_LOGIN).
Yet another possibility is for the program to return a warning that the user's password is about to expire, by using "accept_warning"
instead of "accept"
:
"accept_warning $groups $uid $gid $supplementary_gids $HOME $warning\n"
Where:
$warning
is an appropriate warning message. The message will be processed by NSO according to the setting of /ncs-config/aaa/expiration-warning
in ncs.conf
.
There is also support for token variations of "accept_info"
and "accept_warning"
namely "accept_token_info"
and "accept_token_warning"
. Both "accept_token_info"
and "accept_token_warning"
expect the external program to output exactly the same as described above with the addition of a token after $HOME
:
"accept_token_info $groups $uid $gid $supplementary_gids $HOME $token $info\n"
"accept_token_warning $groups $uid $gid $supplementary_gids $HOME $token $warning\n"
If authentication failed, the program should write "reject"
or "abort"
, possibly followed by a reason for the rejection, and a trailing newline. For example, "reject Bad password\n"
or just "abort\n"
. The difference between "reject"
and "abort"
is that with "reject"
, NSO will try subsequent mechanisms configured for /ncs-config/aaa/auth-order
in ncs.conf
(if any), while with "abort"
, the authentication fails immediately. Thus "abort"
can prevent subsequent mechanisms from being tried, but when external authentication is the last mechanism (as in the default order), it has the same effect as "reject"
.
Supported by some northbound APIs, such as JSON-RPC and CLI over SSH, the external authentication may also choose to issue a challenge:
"challenge $challenge-id $challenge-prompt\n"
The challenge-prompt may be multi-line, why it must be base64 encoded.
For more information on multi-factor authentication, see External Multi-Factor Authentication.
When external authentication is used, the group list returned by the external program is prepended by any possible group information stored locally under the /aaa
tree. Hence when we use external authentication it is indeed possible to have the entire /aaa/authentication
tree empty. The group assignment performed by the external program will still be valid and the relevant groups will be used by NSO when the authorization rules are checked.
When username and password authentication is not feasible, authentication by token validation is possible. Currently, only RESTCONF supports this mode of authentication. It shares all properties of external authentication, but instead of a username and password, it takes a token as input. The output is also almost the same, the only difference is that it is also expected to output a username.
If this feature is configured, NSO will invoke the executable configured in /ncs-config/aaa/external-validation/executable
in ncs.conf
, and pass the token on stdin
using the string notation: "[token;]\n"
.
For example if the user bob
attempts to log over RESTCONF using the token topsecret
, and external validation is enabled, NSO will invoke the configured executable and write "[topsecret;]\n"
on the stdin
stream for the executable.
The task of the executable is then to validate the token, thereby authenticating the user and also establishing the username and username-to-groups mapping.
For example, the executable could be a FUSION client that utilizes some proprietary vendor attributes to retrieve the username and groups of the user from the FUSION server. If token validation is successful, the program should write accept
followed by a space-separated list of groups that the user is a member of, and additional information as described below. Again, assuming that bob
's token indeed was topsecret
, and that bob
is a member of the admin
and the lamers
groups, the program should write accept admin lamers $uid $gid $supplementary_gids $HOME $USER
on its standard output and then exit.
There is a general limit of 16000 bytes of output from the externalvalidation
program.
Thus the format of the output from an externalvalidation
program when token validation authentication is successful should be:
"accept $groups $uid $gid $supplementary_gids $HOME $USER\n"
Where:
$groups
is a space-separated list of the group names the user is a member of.
$uid
is the UNIX integer user ID NSO should use as a default when executing commands for this user.
$gid
is the UNIX integer group ID NSO should use as a default when executing commands for this user.
$supplementary_gids
is a (possibly empty) space-separated list of additional UNIX group IDs the user is also a member of.
$HOME
is the directory that should be used as HOME for this user when NSO executes commands on behalf of this user.
$USER
is the user derived from mapping the token.
It is further possible for the program to return a new token on successful token validation authentication, by using "accept_token"
instead of "accept"
:
"accept_token $groups $uid $gid $supplementary_gids $HOME $USER $token\n"
Where:
$token
is an arbitrary string. NSO will then, for some northbound interfaces, include this token in responses.
It is also possible for the program to return additional information on successful token validation authentication, by using "accept_info"
instead of "accept"
:
"accept_info $groups $uid $gid $supplementary_gids $HOME $USER $info\n"
Where:
$info
is some arbitrary text. NSO will then just append this text to the generated audit log message (CONFD_EXT_LOGIN).
Yet another possibility is for the program to return a warning that the user's password is about to expire, by using "accept_warning"
instead of "accept"
:
"accept_warning $groups $uid $gid $supplementary_gids $HOME $USER $warning\n"
Where:
$warning
is an appropriate warning message. The message will be processed by NSO according to the setting of /ncs-config/aaa/expiration-warning
in ncs.conf
.
There is also support for token variations of "accept_info"
and "accept_warning"
namely "accept_token_info"
and "accept_token_warning"
. Both "accept_token_info"
and "accept_token_warning"
expect the external program to output exactly the same as described above with the addition of a token after $USER
:
"accept_token_info $groups $uid $gid $supplementary_gids $HOME $USER $token $info\n"
"accept_token_warning $groups $uid $gid $supplementary_gids $HOME $USER $token $warning\n"
If token validation authentication fails, the program should write "reject"
or "abort"
, possibly followed by a reason for the rejection and a trailing newline. For example "reject Bad password\n"
or just "abort\n"
. The difference between "reject"
and "abort"
is that with "reject"
, NSO will try subsequent mechanisms configured for /ncs-config/aaa/validation-order
in ncs.conf
(if any), while with "abort"
, the token validation authentication fails immediately. Thus "abort"
can prevent subsequent mechanisms from being tried. Currently, the only available token validation authentication mechanism is the external one.
Supported by some northbound APIs, such as JSON-RPC and CLI over SSH, the external validation may also choose to issue a challenge:
"challenge $challenge-id $challenge-prompt\n"
The challenge prompt may be multi-line, why it must be base64 encoded.
For more information on multi-factor authentication, see External Multi-Factor Authentication.
When username, password, or token authentication is not enough, a challenge may be sent from any of the external authentication mechanisms to the user. A challenge consists of a challenge ID and a base64 encoded challenge prompt, and a user is supposed to send a response to the challenge. Currently, only JSONRPC and CLI over SSH support multi-factor authentication. Responses to challenges of multi-factor authentication have the same output as the token authentication mechanism.
If this feature is configured, NSO will invoke the executable configured in /ncs-config/aaa/external-challenge/executable
in ncs.conf
, and pass the challenge ID and response on stdin
using the string notation: "[challenge-id;response;]\n"
.
For example, a user bob
has received a challenge from external authentication, external validation, or external challenge and then attempts to log in over JSON-RPC with a response to the challenge using challenge ID "22efa",response:"ae457b"
. The external challenge mechanism is enabled, NSO will invoke the configured executable and write "[22efa;ae457b;]\n"
on the stdin
stream for the executable.
The task of the executable is then to validate the challenge ID, and response combination, thereby authenticating the user and also establishing the username and username-to-groups mapping.
For example, the executable could be a RADIUS client which utilizes some proprietary vendor attributes to retrieve the username and groups of the user from the RADIUS server. If challenge ID, response validation is successful, the program should write "accept "
followed by a space-separated list of groups the user is a member of, and additional information as described below. Again, assuming that bob
's challenge ID, the response combination indeed was "22efa", "ae457b"
and that bob
is a member of the admin
and the lamers
groups, the program should write "accept admin lamers $uid $gid $supplementary_gids $HOME $USER\n"
on its standard output and then exit.
There is a general limit of 16000 bytes of output from the externalchallenge
program.
Thus the format of the output from an externalchallenge
program when challenge-based authentication is successful should be:
"accept $groups $uid $gid $supplementary_gids $HOME $USER\n"
Where:
$groups
is a space-separated list of the group names the user is a member of.
$uid
is the UNIX integer user ID NSO should use as a default when executing commands for this user.
$gid
is the UNIX integer group ID NSO should use as a default when executing commands for this user.
$supplementary_gids
is a (possibly empty) space-separated list of additional UNIX group IDs the user is also a member of.
$HOME
is the directory that should be used as HOME for this user when NSO executes commands on behalf of this user.
$USER
is the user derived from mapping the challenge ID, response.
It is further possible for the program to return a token on successful authentication, by using "accept_token"
instead of "accept"
:
"accept_token $groups $uid $gid $supplementary_gids $HOME $USER $token\n"
Where:
$token
is an arbitrary string. NSO will then, for some northbound interfaces, include this token in responses.
It is also possible for the program to return additional information on successful authentication, by using "accept_info"
instead of "accept"
:
"accept_info $groups $uid $gid $supplementary_gids $HOME $USER $info\n"
Where:
$info
is some arbitrary text. NSO will then just append this text to the generated audit log message (CONFD_EXT_LOGIN).
Yet another possibility is for the program to return a warning that the user's password is about to expire, by using "accept_warning"
instead of "accept"
:
"accept_warning $groups $uid $gid $supplementary_gids $HOME $USER $warning\n"
Where:
$warning
is an appropriate warning message. The message will be processed by NSO according to the setting of /ncs-config/aaa/expiration-warning
in ncs.conf
.
There is also support for token variations of "accept_info"
and "accept_warning"
namely "accept_token_info"
and "accept_token_warning"
. Both "accept_token_info"
and "accept_token_warning"
expects the external program to output exactly the same as described above with the addition of a token after $USER
:
"accept_token_info $groups $uid $gid $supplementary_gids $HOME $USER $token $info\n"
"accept_token_warning $groups $uid $gid $supplementary_gids $HOME $USER $token $warning\n"
If authentication fails, the program should write "reject"
or "abort"
, possibly followed by a reason for the rejection and a trailing newline. For example "reject Bad challenge response\n"
or just "abort\n"
. The difference between "reject"
and "abort"
is that with "reject"
, NSO will try subsequent mechanisms configured for /ncs-config/aaa/challenge-order
in ncs.conf
(if any), while with "abort"
, the challenge-response authentication fails immediately. Thus "abort"
can prevent subsequent mechanisms from being tried. Currently, the only available challenge-response authentication mechanism is the external one.
Supported by some northbound APIs, such as JSON-RPC and CLI over SSH, the external challenge may also choose to issue a new challenge:
"challenge $challenge-id $challenge-prompt\n"
The challenge prompt may be multi-line, so it must be base64 encoded.
Note that when using challenges with the CLI over SSH, the /ncs-config/cli/ssh/use-keyboard-interactive>
need to be set to true for the challenges to be sent correctly to the client.
The configuration of the SSH client used may need to be given the option to allow a higher number of allowed number of password prompts, e.g. -o NumberOfPasswordPrompts
, else the default number may introduce an unexpected behavior when the client is presented with multiple challenges.
The Package Authentication functionality allows for packages to handle the NSO authentication in a customized fashion. Authentication data can e.g. be stored remotely, and a script in the package is used to communicate with the remote system.
Compared to external authentication, the Package Authentication mechanism allows specifying multiple packages to be invoked in the order they appear in the configuration. NSO provides implementations for LDAP, SAMLv2, and TACACS+ protocols with packages available in $NCS_DIR/packages/auth/
. Additionally, you can implement your own authentication packages as detailed below.
Authentication packages are NSO packages with the required content of an executable file scripts/authenticate
. This executable basically follows the same API, and limitations, as the external auth script, but with a different input format and some additional functionality. Other than these requirements, it is possible to customize the package arbitrarily.
Package authentication is supported for Single Sign-On (see Single Sign-On in Web UI), JSON-RPC, and RESTCONF. Note that Single Sign-On and (non-batch) JSON-RPC allow all functionality while the RESTCONF interface will treat anything other than a "accept_username
" reply from the package as if authentication failed!
Package authentication is enabled by setting the ncs.conf
options /ncs-config/aaa/package-authentication/enabled
to true, and adding the package by name in the /ncs-config/aaa/package-authentication/packages
list. The order of the configured packages is the order that the packages will be used when attempting to authenticate a user. See ncs.conf(5) in Manual Pages for details.
If this feature is configured in ncs.conf
, NSO will for each configured package invoke script/authenticate
, and pass username, password, and original HTTP request (i.e. the user-supplied next
query parameter), HTTP request, HTTP headers, HTTP body, client source IP, client source port, northbound API context, and protocol on stdin
using the string notation: "[user;password;orig_request;request;headers;body;src-ip;src-port;ctx;proto;]\n"
.
The fields user, password, orig_request, request, headers, and body are all base64 encoded.
If the body length exceeds the partial_post_size
of the RESTCONF server, the body passed to the authenticate script will only contain the string '==nso_package_authentication_partial_body==
'.
The original request will be prefixed with the string ==nso_package_authentication_next==
before the base64 encoded part. This means supplying the next
query parameter value /my-location
will pass the following string to the authentication script: ==nso_package_authentication_next==L215LWxvY2F0aW9u
.
For example, if an unauthenticated user attempts to start a single sign-on process over northbound HTTP-based APIs with the cisco-nso-saml2-auth package, package authentication is enabled and configured with packages, and also single sign-on is enabled, NSO will, for each configured package, invoke the executable scripts/authenticate
and write "[;;;R0VUIC9zc28vc2FtbC9sb2dpbi8gSFRUUC8xLjE=;;;127.0.0.1;59226;webui;https;]\n"
. on the stdin
stream for the executable.
For clarity, the base64 decoded contents sent to stdin
presented: "[;;;GET /sso/saml/login/ HTTP/1.1;;;127.0.0.1;54321;webui;https;]\n"
.
The task of the package is then to authenticate the user and also establish the username-to-groups mapping.
For example, the package could support a SAMLv2 authentication protocol which communicates with an Identity Provider (IdP) for authentication. If authentication is successful, the program should write either "accept"
, or "accept_username"
, depending on whether the authentication is started with a username or if an external entity handles the entire authentication and supplies the username for a successful authentication. (SAMLv2 uses accept_username
, since the IdP handles the entire authentication.) The "accept_username " is followed by a username and then followed by a space-separated list of groups the user is a member of, and additional information as described below. If authentication is successful and the authenticated user bob
is a member of the groups admin
and wheel
, the program should write "accept_username bob admin wheel 1000 1000 100 /home/bob\n"
on its standard output and then exit.
There is a general limit of 16000 bytes of output from the "packageauth" program.
Thus the format of the output from a packageauth
program when authentication is successful should be either the same as from externalauth
(see External Authentication) or the following:
"accept_username $USER $groups $uid $gid $supplementary_gids $HOME\n"
Where:
$USER
is the user derived during the execution of the "packageauth" program.
$groups
is a space-separated list of the group names the user is a member of.
$uid
is the UNIX integer user ID NSO should use as a default when executing commands for this user.
$gid
is the UNIX integer group ID NSO should use as a default when executing commands for this user.
$supplementary_gids
is a (possibly empty) space-separated list of additional UNIX group IDs the user is also a member of.
$HOME
is the directory that should be used as HOME for this user when NSO executes commands on behalf of this user.
In addition to the externalauth
API, the authentication packages can also return the following responses:
unknown '
reason
'
- (reason
being plain-text) if they can't handle authentication for the supplied input.
redirect '
url
'
- (url
being base64 encoded) for an HTTP redirect.
content '
content-type
' '
content
'
- (content-type
being plain-text mime-type and content
being base64 encoded) to relay supplied content.
accept_username_redirect url $USER $groups $uid $gid $supplementary_gids $HOME
- which combines the accept_username
and redirect
.
It is also possible for the program to return additional information on successful authentication, by using "accept_info"
instead of "accept"
:
"accept_info $groups $uid $gid $supplementary_gids $HOME $info\n"
Where:
$info
is some arbitrary text. NSO will then just append this text to the generated audit log message (NCS_PACKAGE_AUTH_SUCCESS).
Yet another possibility is for the program to return a warning that the user's password is about to expire, by using "accept_warning"
instead of "accept"
:
"accept_warning $groups $uid $gid $supplementary_gids $HOME $warning\n"
Where:
$warning
is an appropriate warning message. The message will be processed by NSO according to the setting of /ncs-config/aaa/expiration-warning
in ncs.conf
.
If authentication fails, the program should write "reject"
or "abort"
, possibly followed by a reason for the rejection and a trailing newline. For example "reject 'Bad password'\n"
or just "abort\n"
. The difference between "reject"
and "abort"
is that with "reject"
, NSO will try subsequent mechanisms configured for /ncs-config/aaa/auth-order
, and packages configured for /ncs-config/aaa/package-authentication/packages
in ncs.conf
(if any), while with "abort"
, the authentication fails immediately. Thus "abort"
can prevent subsequent mechanisms from being tried, but when external authentication is the last mechanism (as in the default order), it has the same effect as "reject"
.
When package authentication is used, the group list returned by the package executable is prepended by any possible group information stored locally under the /aaa
tree. Hence when package authentication is used, it is indeed possible to have the entire /aaa/authentication
tree empty. The group assignment performed by the external program will still be valid and the relevant groups will be used by NSO when the authorization rules are checked.
Package authentication will invoke the scripts/authenticate
when a user tries to authenticate using CLI. In this case, only the username, password, client source IP, client source port, northbound API context, and protocol will be passed to the script.
When serving a username/password request, script output other than accept, challenge or abort will be treated as if authentication failed.
When this is enabled, /ncs-config/aaa/package-authentication/package-challenge/enabled
is set to true, packages will also be used to try to resolve challenges sent to the server and are only supported by CLI over SSH. The script script/challenge
will be invoked passing challenge ID, response, client source IP, client source port, northbound API context, and protocol on stdin
using the string notation: "[challengeid;response;src-ip;src-port;ctx;proto;]\n"
. The output should follow that of the authenticate script.
The fields challengeid
and response are base64 encoded when passed to the script.
NSO communicates with clients (client libraries, ncs_cli, and similar) using the NSO IPC socket. The protocol used allows the client to provide user and group information to use for authorization in NSO, effectively delegating authentication to the client.
By default, only local connections to the IPC socket are allowed. If all local clients are considered trusted, the socket can provide unauthenticated access, with the client-supplied user name. This is what the --user
option of ncs_cli does. For example:
connects to NSO as the user admin
. The same is possible for the group. This unauthenticated access is currently the default.
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. NSO implements it as an access check, where every IPC client must prove that it has access to a pre-shared key. See Restricting Access to the IPC Port on how to enable it.
Once a user is authenticated, group membership must be established. A single user can be a member of several groups. Group membership is used by the authorization rules to decide which operations a certain user is allowed to perform. Thus the NSO AAA authorization model is entirely group-based. This is also sometimes referred to as role-based authorization.
All groups are stored under /nacm/groups
, and each group contains a number of usernames. The ietf-netconf-acm.yang
model defines a group entry:
The tailf-acm.yang
model augments this with a gid
leaf:
A valid group entry could thus look like:
The above XML data would then mean that users bob
and joe
are members of the admin
group. The users need not necessarily exist as actual users under /aaa/authentication/users
in order to belong to a group. If for example PAM authentication is used, it does not make sense to have all users listed under /aaa/authentication/users
.
By default, the user is assigned to groups by using any groups provided by the northbound transport (e.g. via the ncs_cli
or netconf-subsys
programs), by consulting data under /nacm/groups
, by consulting the /etc/group
file, and by using any additional groups supplied by the authentication method. If /nacm/enable-external-groups
is set to "false", only the data under /nacm/groups
is consulted.
The resulting group assignment is the union of these methods, if it is non-empty. Otherwise, the default group is used, if configured ( /ncs-config/aaa/default-group
in ncs.conf
).
A user entry has a UNIX uid and UNIX gid assigned to it. Groups may have optional group IDs. When a user is logged in, and NSO tries to execute commands on behalf of that user, the uid/gid for the command execution is taken from the user entry. Furthermore, UNIX supplementary group IDs are assigned according to the gid
's in the groups where the user is a member.
Once a user is authenticated and group membership is established, when the user starts to perform various actions, each action must be authorized. Normally the authorization is done based on rules configured in the AAA data model as described in this section.
The authorization procedure first checks the value of /nacm/enable-nacm
. This leaf has a default of true
, but if it is set to false
, all access is permitted. Otherwise, the next step is to traverse the rule-list
list:
If the group
leaf-list in a rule-list
entry matches any of the user's groups, the cmdrule
list entries are examined for command authorization, while the rule
entries are examined for RPC, notification, and data authorization.
The tailf-acm.yang
module augments the rule-list
entry in ietf-netconf-acm.yang
with a cmdrule
list:
Each rule has seven leafs. The first is the name
list key, the following three leafs are matching leafs. When NSO tries to run a command, it tries to match the command towards the matching leafs and if all of context
, command
, and access-operations
match, the fifth field, i.e. the action
, is applied.
name
: name
is the name of the rule. The rules are checked in order, with the ordering given by the YANG ordered-by user
semantics, i.e. independent of the key values.
context
: context
is either of the strings cli
, webui
, or *
for a command rule. This means that we can differentiate authorization rules for which access method is used. Thus if command access is attempted through the CLI, the context will be the string cli
whereas for operations via the Web UI, the context will be the string webui
.
command
: This is the actual command getting executed. If the rule applies to one or several CLI commands, the string is a space-separated list of CLI command tokens, for example request system reboot
. If the command applies to Web UI operations, it is a space-separated string similar to a CLI string. A string that consists of just *
matches any command.
In general, we do not recommend using command rules to protect the configuration. Use rules for data access as described in the next section to control access to different parts of the data. Command rules should be used only for CLI commands and Web UI operations that cannot be expressed as data rules.
The individual tokens can be POSIX extended regular expressions. Each regular expression is implicitly anchored, i.e. an ^
is prepended and a $
is appended to the regular expression.
access-operations
: access-operations
is used to match the operation that NSO tries to perform. It must be one or both of the "read" and "exec" values from the access-operations-type
bits type definition in ietf-netconf-acm.yang
, or "*" to match any operation.
action: If all of the previous fields match, the rule as a whole matches and the value of action
will be taken. I.e. if a match is found, a decision is made whether to permit or deny the request in its entirety. If action
is permit
, the request is permitted, if action
is deny
, the request is denied and an entry is written to the developer log.
log-if-permit
: If this leaf is present, an entry is written to the developer log for a matching request also when action
is permit
. This is very useful when debugging command rules.
comment
: An optional textual description of the rule.
For the rule processing to be written to the devel log, the /ncs-config/logs/developer-log-level
entry in ncs.conf
must be set to trace
.
If no matching rule is found in any of the cmdrule
lists in any rule-list
entry that matches the user's groups, this augmentation from tailf-acm.yang
is relevant:
If read
access is requested, the value of /nacm/cmd-read-default
determines whether access is permitted or denied.
If exec
access is requested, the value of /nacm/cmd-exec-default
determines whether access is permitted or denied.
If access
is permitted due to one of these default leafs, the /nacm/log-if-default-permit
has the same effect as the log-if-permit
leaf for the cmdrule
lists.
The rules in the rule
list are used to control access to rpc operations, notifications, and data nodes defined in YANG models. Access to invocation of actions (tailf:action
) is controlled with the same method as access to data nodes, with a request for exec
access. ietf-netconf-acm.yang
defines a rule
entry as:
tailf-acm
augments this with two additional leafs:
Similar to the command access check, whenever a user through some agent tries to access an RPC, a notification, a data item, or an action, access is checked. For a rule to match, three or four leafs must match and when a match is found, the corresponding action is taken.
We have the following leafs in the rule
list entry.
name
: The name of the rule. The rules are checked in order, with the ordering given by the YANG ordered-by user
semantics, i.e. independent of the key values.
module-name
: The module-name
string is the name of the YANG module where the node being accessed is defined. The special value *
(i.e. the default) matches all modules.\
rpc-name / notification-name / path
: This is a choice between three possible leafs that are used for matching, in addition to the module-name
:
rpc-name
: The name of an RPC operation, or *
to match any RPC.
notification-name
: the name of a notification, or *
to match any notification.
path
: A restricted XPath expression leading down into the populated XML tree. A rule with a path specified matches if it is equal to or shorter than the checked path. Several types of paths are allowed.
Tagpaths that do not contain any keys. For example /ncs/live-device/live-status
.
Instantiated key: as in /devices/device[name="x1"]/config/interface
matches the interface configuration for managed device "x1" It's possible to have partially instantiated paths only containing some keys instantiated - i.e. combinations of tagpaths and keypaths. Assuming a deeper tree, the path /devices/device/config/interface[name="eth0"]
matches the eth0
interface configuration on all managed devices.
The wild card at the end as in: /services/web-site/*
does not match the website service instances, but rather all children of the website service instances.\
Thus, the path in a rule is matched against the path in the attempted data access. If the attempted access has a path that is equal to or longer than the rule path - we have a match.
If none of the leafs rpc-name
, notification-name
, or path
are set, the rule matches for any RPC, notification, data, or action access.
context
: context
is either of the strings cli
, netconf
, webui
, snmp
, or *
for a data rule. Furthermore, when we initiate user sessions from MAAPI, we can choose any string we want. Similarly to command rules, we can differentiate access depending on which agent is used to gain access.
access-operations
: access-operations
is used to match the operation that NSO tries to perform. It must be one or more of the "create", "read", "update", "delete" and "exec" values from the access-operations-type
bits type definition in ietf-netconf-acm.yang
, or "*" to match any operation.
action
: This leaf has the same characteristics as the action
leaf for command access.
log-if-permit
: This leaf has the same characteristics as the log-if-permit
leaf for command access.
comment
: An optional textual description of the rule.
If no matching rule is found in any of the rule
lists in any rule-list
entry that matches the user's groups, the data model node for which access is requested is examined for the presence of the NACM extensions:
If the nacm:default-deny-all
extension is specified for the data model node, the access is denied.
If the nacm:default-deny-write
extension is specified for the data model node, and create
, update
, or delete
access is requested, the access is denied.
If examination of the NACM extensions did not result in access being denied, the value (permit
or deny
) of the relevant default leaf is examined:
If read
access is requested, the value of /nacm/read-default
determines whether access is permitted or denied.
If create
, update
, or delete
access is requested, the value of /nacm/write-default
determines whether access is permitted or denied.
If exec
access is requested, the value of /nacm/exec-default
determines whether access is permitted or denied.
If access is permitted due to one of these default leafs, this augmentation from tailf-acm.yang
is relevant:
I.e. it has the same effect as the log-if-permit
leaf for the rule
lists, but for the case where the value of one of the default leafs permits access.
When NSO executes a command, the command rules in the authorization database are searched, The rules are tried in order, as described above. When a rule matches the operation (command) that NSO is attempting, the action of the matching rule is applied - whether permit or deny.
When actual data access is attempted, the data rules are searched. E.g. when a user attempts to execute delete aaa
in the CLI, the user needs delete access to the entire tree /aaa
.
Another example is if a CLI user writes show configuration aaa TAB
it suffices to have read access to at least one item below /aaa
for the CLI to perform the TAB completion. If no rule matches or an explicit deny rule is found, the CLI will not TAB complete.
Yet another example is if a user tries to execute delete aaa authentication users
, we need to perform a check on the paths /aaa
and /aaa/authentication
before attempting to delete the sub-tree. Say that we have a rule for path /aaa/authentication/users
which is a permit rule and we have a subsequent rule for path /aaa
which is a deny rule. With this rule set the user should indeed be allowed to delete the entire /aaa/authentication/users
tree but not the /aaa
tree nor the /aaa/authentication
tree.
We have two variations on how the rules are processed. The easy case is when we actually try to read or write an item in the configuration database. The execution goes like this:
The second case is when we execute TAB completion in the CLI. This is more complicated. The execution goes like this:
The idea is that as we traverse (through TAB) down the XML tree, as long as there is at least one rule that can possibly match later, once we have more data, we must continue. For example, assume we have:
"/system/config/foo" --> permit
"/system/config" --> deny
If we in the CLI stand at "/system/config"
and hit TAB we want the CLI to show foo
as a completion, but none of the other nodes that exist under /system/config
. Whereas if we try to execute delete /system/config
the request must be rejected.
By default, NACM rules are configured for the entire tailf:action
or YANG 1.1 action
statements, but not for input
statement child leafs. To override this behavior, and enable NACM rules on input
leafs, set the following parameter to 'true': /ncs-config/aaa/action-input-rules/enabled
. When enabled all action input leafs given to an action will be validated for NACM rules. If broad 'deny' NACM rules are used, you might need to add 'permit' rules for the affected action input leafs to allow actions to be used with parameters.
By design NACM rules are ignored for changes done by services - FASTMAP, Reactive FASTMAP, or Nano services. The reasoning behind this is that a service package can be seen as a controlled way to provide limited access to devices for a user group that is not allowed to apply arbitrary changes on the devices.
However, there are NSO installations where this behavior is not desired, and NSO administrators want to enforce NACM rules even on changes done by services. For this purpose, the leaf called /nacm/enforce-nacm-on-services
is provided. By default, it is set to false
.
Note however that currently, even with this leaf set to true, there are limitations. Namely, the post-actions for nano-services are run in a user session without any access checks. Besides that, NACM rules are not enforced on the read operations performed in the service callbacks.
It might be desirable to deny everything for a user group and only allow access to a specific service. This pattern could be used to allow an operator to provision the service, but deny everything else. While this pattern works for a normal FASTMAP service, there are some caveats for stacked services, Reactive FASTMAP, and Nano services. For these kinds of services, in addition to the service itself, access should be provided to the user group for the following paths:
In case of stacked services, the user group needs read and write access to the leaf private/re-deploy-counter
under the bottom service. Otherwise, the user will not be able to redeploy the service.
In the case of Reactive FASTMAP or Nano services, the user group needs read and write access to the following:
/zombies
/side-effect-queue
/kickers
In deployments with many devices, it can become cumbersome to handle data authorization per device. To help with this there is a rule type that works on device group membership (for more on device groups, see Device Groups). To do this, devices are added to different device groups, and the rule type device-group-rule
is used.
The IETF NACM rule type is augmented with a new rule type named device-group-rule
which contains a leafref to the device groups. See the following example.
In the example below, we configure two device groups based on different regions and add devices to them.
In the example below, we configure an operator for the us_east
region:
In the example below, we configure the device group rules and refer to the device group and the us_east
group.
In summary device group authorization gives a more compact configuration for deployments where devices can be grouped and authorization can be done on a device group basis.
Modifications on the device-group subtree are recommended to be controlled by a limited set of users.
Assume that we have two groups, admin
and oper
. We want admin
to be able to see and edit the XML tree rooted at /aaa
, but we do not want users who are members of the oper
group to even see the /aaa
tree. We would have the following rule list and rule entries. Note, here we use the XML data from tailf-aaa.yang
to exemplify. The examples apply to all data, for all data models loaded into the system.
If we do not want the members of oper
to be able to execute the NETCONF operation edit-config
, we define the following rule list and rule entries:
To spell it out, the above defines four elements to match. If NSO tries to perform a netconf
operation, which is the operation edit-config
, and the user who runs the command is a member of the oper
group, and finally it is an exec
(execute) operation, we have a match. If so, the action is deny
.
The path
leaf can be used to specify explicit paths into the XML tree using XPath syntax. For example the following:
Explicitly allows the admin
group to change the password for precisely the bob
user when the user is using the CLI. Had path
been /aaa/authentication/users/user/password
the rule would apply to all password elements for all users. Since the path
leaf completely identifies the nodes that the rule applies to, we do not need to give tailf-aaa
for the module-name
leaf.
NSO applies variable substitution, whereby the username of the logged-in user can be used in a path
. Thus:
The above rule allows all users that are part of the admin
group to change their own passwords only.
A member of oper
is able to execute NETCONF operation action
if that member has exec
access on NETCONF RPC action
operation, read
access on all instances in the hierarchy of data nodes that identifies the specific action in the data store, and exec
access on the specific action. For example, an action is defined as below.
To be able to execute double
action through NETCONF RPC, the members of oper
need the following rule list and rule entries.
Or, a simpler rule set as the following.
Finally, if we wish members of the oper
group to never be able to execute the request system reboot
command, also available as a reboot
NETCONF rpc, we have:
In this section, we list some tips to make it easier to troubleshoot NACM rules.
Use log-if-permit
and log-if-default-permit
together with the developer log level set to trace
.
Use the tailf-acm.yang
module augmentation log-if-permit
leaf for rules with action
permit
. When those rules trigger a permit action a trace entry is added to the developer log. To see trace entries make sure the /ncs-config/logs/developer-log-level
is set to trace
.
If you have a default rule with action
permit
you can use the log-if-default-permit
leaf instead.
NACM rules are read at the start of the session and are used throughout the session.
When a user session is created it will gather the authorization rules that are relevant for that user's group(s). The rules are used throughout the user session lifetime. When we update the AAA rules the active sessions are not affected. For example, if an administrator updates the NACM rules in one session the update will not apply to any other currently active sessions. The updates will apply to new sessions created after the update.
Explicitly state NACM groups when starting the CLI. For example ncs_cli -u oper -g oper
.
It is the user's group membership that determines what rules apply. Starting the CLI using the ncs_cli
command without explicitly setting the groups, defaults to the actual UNIX groups the user is a member of. On Darwin, one of the default groups is usually admin
, which can lead to the wrong group being used.
Be careful with namespaces in rulepaths.
Unless a rulepath is made explicit by specifying namespace it will apply to that specific path in all namespaces. Below we show parts of an example from RFC 8341, where the path
element has an xmlns
attribute and the path is namespaced. If these would not have been namespaced, the rules would not behave as expected.
In the example above (Excerpt from RFC 8341 Appendix A.4), the path is namespaced.
NSO's AAA subsystem will cache the AAA information in order to speed up the authorization process. This cache must be updated whenever there is a change to the AAA information. The mechanism for this update depends on how the AAA information is stored, as described in the following two sections.
To start NSO, the data models for AAA must be loaded. The defaults in the case that no actual data is loaded for these models allow all read and exec access, while write access is denied. Access may still be further restricted by the NACM extensions, though - e.g. the /nacm
container has nacm:default-deny-all
, meaning that not even read access is allowed if no data is loaded.
The NSO installation ships with an XML initialization file containing AAA configuration. The file is called aaa_init.xml
and is, by default, copied to the CDB directory by the NSO install scripts.
The local installation variant, targeting development only, defines two users, admin
and oper
with passwords set to admin
and oper
respectively for authentication. The two users belong to user groups with NACM rules restricting their authorization level. The system installation aaa_init.xml
variant, targeting production deployment, defines NACM rules only as users are, by default, authenticated using PAM. The NACM rules target two user groups, ncsadmin
and ncsoper
. Users belonging to the ncsoper
group are limited to read-only access.
The default aaa_init.xml
file provided with the NSO system installation must not be used as-is in a deployment without reviewing and verifying that every NACM rule in the file matches
Normally the AAA data will be stored as configuration in CDB. This allows for changes to be made through NSO's transaction-based configuration management. In this case, the AAA cache will be updated automatically when changes are made to the AAA data. If changing the AAA data via NSO's configuration management is not possible or desirable, it is alternatively possible to use the CDB operational data store for AAA data. In this case, the AAA cache can be updated either explicitly e.g. by using the maapi_aaa_reload()
function, see the confd_lib_maapi(3) in the Manual Pages manual page, or by triggering a subscription notification by using the subscription lock when updating the CDB operational data store, see Using CDB in Development.
Some applications may not want to expose the AAA data to end users in the CLI or the Web UI. Two reasonable approaches exist here and both rely on the tailf:export
statement. If a module has tailf:export none
it will be invisible to all agents. We can then either use a transform whereby we define another AAA model and write a transform program that maps our AAA data to the data that must exist in tailf-aaa.yang
and ietf-netconf-acm.yang
. This way we can choose to export and and expose an entirely different AAA model.
Yet another very easy way out, is to define a set of static AAA rules whereby a set of fixed users and fixed groups have fixed access to our configuration data. Possibly the only field we wish to manipulate is the password field.