Access to any part of the configuration can be restricted by defining access control rules. The access control model that the Curity Identity Server uses is called Network Configuration Access Control Model (NACM). This is an international standard defined in RFC 8341. By basing the access control model on an open standard, it is very clear how rules are defined and enforced. While that specification lays this out in detail, this page serves as a lighter introduction to NACM and specifically explains how it is applied in the Curity Identity Server.
It is important to understand that rules are defined in the data model. This means that any backups of the configuration will include the access control rules as well. It also means they can be parameterized in the typical way. This seamless inclusion in the data handling of the configuration should make it simpler to integrate into normal workflows established by the identity server administrators. It also means that rules can be defined in the GUI or the other management interfaces. The GUI and CLI make this job particularly easy. To see how this can be done, the structure of the NACM rules is described below.
Firstly, rules are defined in the nacm subtree, which is a child of the top-most configuration root. There are a few main parts:
nacm
Using the CLI, these can be viewed with the simple command show configuration nacm. When doing so, output similar to the following is shown:
show configuration nacm
read-default permit; # permit write-default permit; # deny groups { group admin { user-name [ admin ]; } } rule-list admin { group [ admin ]; rule any-access { module-name *; # * access-operations *; # * action permit; context *; # * } }
In Listing 338, the write-default has had it’s default changed from deny to permit; this means that if any data is updated and there is no applicable rule, access will be allowed. The previous listing also defines one group, admin, and a rule that applies to it. Any number of groups can be added to the list and users can be added to each group. Doing so is very intuitive using the UI and CLI, but it is important to understand that users are either defined in the aaa section of the configuration or identified using an external authentication source (e.g., AD). Which depends on whether external authentication of administrators is enabled or not; when it isn’t, the users in the NACM groups will be those contained in the aaa section of the configuration and will be whatever the external authentication source asserts as the username if it is.
write-default
deny
permit
group
admin
aaa
The heart of the NACM system is the rules. It is important to understand that these can be applied to all management interfaces (the UI, CLI, and the RESTCONF API) or just a subset. These are what is referred to as the context. In the example above, the context is *, the default. This means the rule applies to all management interfaces. An example of a context that only applies to the RESTCONF API and the UI would be this:
context
*
rule test-rule1 { access-operations *; action permit; context rest; } rule test-rule2 { access-operations *; action permit; context webui; }
Note in Listing 339 how the rule has to be repeated for each context; multiple cannot be separated by a comma or space or anything else.
Additionally, rules have an action and list of access-operations. The action is either permit or deny which have the obvious meaning. The access-operations is a set containing create, read, update and/or delete. (It may also contain exec but this is unused by the Curity Identity Server). When the set includes create the user to whom the rule applies will be able to create new configuration; likewise for read, update, and delete.
action
access-operations
create
read
update
delete
exec
The applicability of a rule is primarily affected by the path. The rules in Listing 338 and Listing 339 have no path, so they apply to all configuration.[1] Using the path element, a rule can be applied to specific data nodes or entire subtrees. This is done using XPath 1.0 expressions. An example of a rule that applies to a specific data node is shown in Listing 340:
path
rule test-rule2 { access-operation *; action permit; context *; path /facilities; }
This rule applies just to the facilities node itself, not its children. This is not a very useful rule because facilities has no leaves, only children. In this particular case, a more useful path would be /facilities/*. This means the rule applies to not only facilities, but also all of its children, like HTTP clients, data sources, etc. The “trick” here is the trailing /*; in XPath, this kind of expression selects a node and its children.
/facilities/*
/*
Tip
The entire data model of rules, rule lists and the NACM configuration subtree is described in section 3.5 or RFC 8341.
It is very easy to define rules in the CLI and they can also be created using the RESTCONF API. However, the GUI makes it very intuitive and easy. It is especially easy to determine the path, and define rules that apply to particular data nodes (and their children). There are kinds of rules that cannot be defined in the GUI, however, and it takes a very advanced user to be able to define rules in the CLI that will be understood by the GUI. Also, it isn’t hard to lock out all uses (including the root admin user) if rules are defined incorrectly in the CLI. For these reasons, it is suggested to define all rules in the GUI, and only use the CLI when some advanced case comes up. After doing so, export the NACM rules and apply them to other runtime environments using the normal techniques for configuration data management.
Only users in the admin group are allowed to set permissions in the UI. When an administrator logs in, every setting that can have permissions defined will have a button in the toolbar that opens the permissions modal. The two variants of this button are shown in the following figure:
Fig. 202 Permissions toolbar buttons used where (A) space allows and (B) on space-constrained views
Whichever button is displayed, when clicked, a permission modal will be shown. This dialogue can be used to define rules for the selected configuration. The modal will be similar to the following:
Fig. 203 Permissions modal with multiple groups selected
This view is composed of three primary parts:
Adding groups can be done by selecting them from the Groups drowdown list (A). If a new group is needed, it can be defined by selecting the New Group button (B). If a new group is created using this button and the subsequently shown modal, it will be added automatically to selected groups (C). Each group that is selected in (C) will cause the permissions (E) and context (F) to be updated. This allows for rules to be created for each group, and to thus restrict access on a per group basis. For instance, the permissions and context for all groups (denoted by the * in the groups list) in Fig. 203 do not have any permissions; this applies to all management interfaces. However, rules can also be defined for specific groups. When selected, the permissions and context to which the rule applies will be shown.
After rules have been defined, they can be viewed by reopening the modal of the particular setting to which they apply. All rules defined in the system can also be viewed on the Permissions page. This page is accessible by selecting System → Permissions or by selecting Permissions from the account menu. There, all permissions will be shown. Those that can be understood by the admin UI will be editable, whereas those that cannot will be shown but disabled. For the enabled ones, an Action menu is available. When selected, the administrator can alter the rules (e.g., to add groups or change the applicable context) by selecting Edit. The rule can also be deleted, and it’s possible to navigate to the configuration the rule applies to by selecting Go to Element. As shown in Fig. 204, it is also possible to configure the default read and write access of the system. As described in the next section, these apply when access to a configuration setting is requested for which an explicit rule is undefined.
Fig. 204 Permissions page showing default access, readonly rules and an editable rule with its Actions menu
Rules that govern access to the DevOps Dashboard can also be configured in the admin UI.[2] To do so, go to DevOps page accessible under System → Administrators. Initially, no rules exist. In such a case, new rules can be configured by clicking the Configure Permissions button. When this is done, a wizard is started. The first page asks which group the rule should be for. On the following page, the wizard asks if:
The former will grant read-only access to alarms if selected. If OAuth client access isn’t allowed, the wizard will end at this point. If client access is granted, however, additional pages are shown. In this case, the next page in the wizard allows an administrator to grant access to a certain OAuth profile or all of them:
Fig. 205 Selecting a certain OAuth profile or allowed developers using the DevOps Dashboard to access all OAuth profiles
When Selected Profiles is chosen, a multi-select widget is shown where certain OAuth profiles can be selected. Next, a subset of OAuth clients or all of them (in all or the specific OAuth profiles previously selected) can be granted access to.
On the next page, the administrator has the option to allow developers to modify scopes or not. The default is that they cannot, making scopes read-only in the DevOps Dashboard.
Fig. 206 Allowing access to scopes by developers in the DevOps Dashboard or not
On the final page, an administrator can select to grant read-only or read-write access to the previously selected OAuth clients.
Once the rules are created, they are listed on the page in a table view. From this view, each rule can be edited, deleted, or duplicated using the options in the Actions menu.
Note
Rules for the dashboard are not listed on Permissions page
When a user attempts to access any of the configuration (using any of the administrative interfaces), the configured rules defined in the system are evaluated to determine if the request should be allowed or not. How this determination is made is defined in section 3.4.5 of the NACM RFC; this is probably the most important part of the spec as it relates to a Curity Identity Server administer, so it is paraphrased in the following pseudocode:
For each group, g, that the user is in, do the following: From the first rule-list to the last in the NACM subtree, let the current rule-list be denoted by current-rule-list and do the following: If the group list of current-rule-list contains * or g, do the following: For each rule, r, in current-rule-list, check if all of the following are true: r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3] The access-operations of r is either * or it contains: read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting. If the criteria above were true and a match was found then the search terminates with the following decision: The operation is allowed if the action of r is permit; Otherwise, the operation is denied. At this point, no matching rule was found in any rule-list elements that have a group that contains a group that the user is in or else the user is not in any groups. If the read-default setting (described in the previous subsection) is toggled on (set to permit) and the requested operations is a read operation, then access is granted. Otherwise, the requested data and any of its children are excluded from the response. Otherwise, if the write-default setting is toggled on (set to permit), then permit the request; otherwise, deny it.
For each group, g, that the user is in, do the following:
g
From the first rule-list to the last in the NACM subtree, let the current rule-list be denoted by current-rule-list and do the following: If the group list of current-rule-list contains * or g, do the following: For each rule, r, in current-rule-list, check if all of the following are true: r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3] The access-operations of r is either * or it contains: read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting. If the criteria above were true and a match was found then the search terminates with the following decision: The operation is allowed if the action of r is permit; Otherwise, the operation is denied.
From the first rule-list to the last in the NACM subtree, let the current rule-list be denoted by current-rule-list and do the following:
rule-list
current-rule-list
If the group list of current-rule-list contains * or g, do the following: For each rule, r, in current-rule-list, check if all of the following are true: r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3] The access-operations of r is either * or it contains: read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting. If the criteria above were true and a match was found then the search terminates with the following decision: The operation is allowed if the action of r is permit; Otherwise, the operation is denied.
If the group list of current-rule-list contains * or g, do the following:
For each rule, r, in current-rule-list, check if all of the following are true: r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3] The access-operations of r is either * or it contains: read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting. If the criteria above were true and a match was found then the search terminates with the following decision: The operation is allowed if the action of r is permit; Otherwise, the operation is denied.
For each rule, r, in current-rule-list, check if all of the following are true:
rule
r
r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3] The access-operations of r is either * or it contains: read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting. If the criteria above were true and a match was found then the search terminates with the following decision: The operation is allowed if the action of r is permit; Otherwise, the operation is denied.
r has a path that matches the requested setting or r has a path ending in /* and the requested setting in a child of the path or there is no path at all.[3]
The access-operations of r is either * or it contains:
read and the request is to read a setting; create and the request is to create a setting; delete and the request is to delete a setting; or update and the request is to update an existing setting.
If the criteria above were true and a match was found then the search terminates with the following decision:
The operation is allowed if the action of r is permit; Otherwise, the operation is denied.
At this point, no matching rule was found in any rule-list elements that have a group that contains a group that the user is in or else the user is not in any groups.
If the read-default setting (described in the previous subsection) is toggled on (set to permit) and the requested operations is a read operation, then access is granted. Otherwise, the requested data and any of its children are excluded from the response.
read-default
Otherwise, if the write-default setting is toggled on (set to permit), then permit the request; otherwise, deny it.
rpc-name
notification-name