RFC 8341

Network Configuration Access Control Model

πŸ“… published March 2018, from ietf

RFC 8341: Network Configuration Access Control Model πŸ¦‹

okay bestie, this one is about who gets to touch what on a NETCONF or RESTCONF server πŸ” It's giving bouncer at the club energy πŸ’…

Quick ID card first. Written by A. Bierman (YumaWorks) and M. Bjorklund (Tail-f Systems). It's a Standards Track document, which means it's an actual Internet standard, and it's STD 91 🌸 Published March 2018, ISSN 2070-1721. It obsoletes RFC 6536, so if you're still reading 6536, you're reading the outdated version πŸ™ˆ The header has no "Updates" line.


Abstract ✨

Okay so, network configuration interfaces for NETCONF or RESTCONF need to be structured, secure, easy for humans to use, and able to work across different vendors 🫢 Right now there's no standard way to limit which NETCONF or RESTCONF operations and content a particular user can get at, from some preconfigured subset of everything the server has. This doc defines that access control model. Main character behavior πŸ‘‘

This document obsoletes RFC 6536.


Status of This Memo πŸ“œ

This is an Internet Standards Track document, so it's official. It's a product of the Internet Engineering Task Force (IETF), it represents the consensus of the IETF community, it got public review, and the Internet Engineering Steering Group (IESG) approved it for publication πŸ’–

For more on Internet Standards, check Section 2 of RFC 7841. You can find the current status, any errata, and a way to send feedback at https://www.rfc-editor.org/info/rfc8341 πŸ“


Copyright (c) 2018 IETF Trust and the persons identified as the document authors. All rights reserved 🌈

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info), as they stand on the publication date. Read those carefully, because they spell out your rights and restrictions for this doc 🧚 If you pull Code Components out of this document, they have to include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as described in that same license πŸ”₯


Table of Contents πŸ—‚οΈ

   1. Introduction ....................................................4
      1.1. Terminology ................................................4
      1.2. Changes since RFC 6536 .....................................6
   2. Access Control Design Objectives ................................7
      2.1. Access Control Points ......................................7
      2.2. Simplicity .................................................8
      2.3. Procedural Interface .......................................8
      2.4. Datastore Access ...........................................8
      2.5. Users and Groups ...........................................8
      2.6. Maintenance ................................................9
      2.7. Configuration Capabilities .................................9
      2.8. Identifying Security-Sensitive Content .....................9
   3. NETCONF Access Control Model (NACM) ............................10
      3.1. Overview ..................................................10
           3.1.1. Features ...........................................10
           3.1.2. External Dependencies ..............................11
           3.1.3. Message Processing Model ...........................11
      3.2. Datastore Access ..........................................14
           3.2.1. Mapping New Datastores to NACM .....................14
           3.2.2. Access Rights ......................................14
           3.2.3. RESTCONF Methods ...................................15
           3.2.4. <get> and <get-config> Operations ..................16
           3.2.5. <edit-config> Operation ............................16
           3.2.6. <copy-config> Operation ............................18
           3.2.7. <delete-config> Operation ..........................18
           3.2.8. <commit> Operation .................................19
           3.2.9. <discard-changes> Operation ........................19
           3.2.10. <kill-session> Operation ..........................19

      3.3. Model Components ..........................................19
           3.3.1. Users ..............................................19
           3.3.2. Groups .............................................20
           3.3.3. Emergency Recovery Session .........................20
           3.3.4. Global Enforcement Controls ........................20
                  3.3.4.1. enable-nacm Switch ........................20
                  3.3.4.2. read-default Switch .......................20
                  3.3.4.3. write-default Switch ......................21
                  3.3.4.4. exec-default Switch .......................21
                  3.3.4.5. enable-external-groups Switch .............22
           3.3.5. Access Control Rules ...............................22
      3.4. Access Control Enforcement Procedures .....................22
           3.4.1. Initial Operation ..................................23
           3.4.2. Session Establishment ..............................23
           3.4.3. "access-denied" Error Handling .....................23
           3.4.4. Incoming RPC Message Validation ....................24
           3.4.5. Data Node Access Validation ........................26
           3.4.6. Outgoing <notification> Authorization ..............29
      3.5. Data Model Definitions ....................................31
           3.5.1. Data Organization ..................................31
           3.5.2. YANG Module ........................................32
   4. IANA Considerations ............................................42
   5. Security Considerations ........................................42
      5.1. NACM Configuration and Monitoring Considerations ..........43
      5.2. General Configuration Issues ..............................45
      5.3. Data Model Design Considerations ..........................47
   6. References .....................................................47
      6.1. Normative References ......................................47
      6.2. Informative References ....................................49
   Appendix A. Usage Examples ........................................50
     A.1. <groups> Example ...........................................50
     A.2. Module Rule Example ........................................51
     A.3. Protocol Operation Rule Example ............................53
     A.4. Data Node Rule Example .....................................55
     A.5. Notification Rule Example ..................................57
   Authors' Addresses ................................................58

1. Introduction 🌸

Okay so, NETCONF and RESTCONF don't come with any standard way to restrict which protocol operations and content each user is allowed to access. That's kind of a big gap, ngl πŸ™ˆ

What people actually need is interoperable control over who gets access to which administrator-picked parts of the NETCONF or RESTCONF content on a given server πŸ’–

This document covers access control for the Operations and Content layers of NETCONF, defined in [RFC6241], and RESTCONF, defined in [RFC8040]. It has three main sections:

  1. Access Control Design Objectives
  2. NETCONF Access Control Model (NACM)
  3. YANG Data Model (ietf-netconf-acm.yang)

YANG version 1.1 [RFC7950] adds two new constructs that need special access control handling πŸ‘€ The "action" statement is like the "rpc" statement, except it lives inside a data node. The "notification" statement can also live inside a data node. Two new things, two new rules, iykyk πŸ¦‹

1.1. Terminology πŸ“š

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

These terms are defined in [RFC8342] and aren't redefined here 🫢

  • datastore
  • configuration datastore
  • conventional configuration datastore
  • candidate configuration datastore
  • running configuration datastore
  • startup configuration datastore
  • operational state datastore
  • client
  • server

These terms are defined in [RFC6241] and aren't redefined here πŸ’…

  • protocol operation
  • session
  • user

These terms are defined in [RFC7950] and aren't redefined here ✨

  • action
  • data node
  • data definition statement

These terms are defined in [RFC8040] and aren't redefined here 🌈

  • data resource
  • datastore resource
  • operation resource
  • target resource

This term is defined in [RFC7230] and isn't redefined here 🧚

  • request URI

These terms get used all over this document, so here's the tea β˜•

access control: A security feature provided by the server that lets an administrator restrict access to a subset of all protocol operations and data, based on various criteria.

access control model (ACM): A conceptual model used to configure and monitor the access control procedures the administrator wants, so they can enforce a particular access control policy.

access control rule: The criterion used to decide whether a particular access operation will be permitted or denied.

access operation: How a request tries to access a conceptual object. It's one of "none", "read", "create", "delete", "update", or "execute" πŸ’€

data node hierarchy: The hierarchy of data nodes that identifies the specific "action" or "notification" node in the datastore.

recovery session: A special administrative session that gets unlimited NETCONF access and is exempt from all access control enforcement. The mechanism or mechanisms a server uses to control and identify whether a session is a recovery session are implementation specific and outside the scope of this document πŸ”₯

write access: Shorthand for the "create", "delete", and "update" access operations πŸ“

1.2. Changes since RFC 6536 ✨

okay so the NACM procedures and data model got a glow-up to support the new data modeling stuff in version 1.1 of the YANG data modeling language πŸ’– The action and notification statements can now live inside data nodes, so you can define operations and notifications that are specific to a particular data model πŸ¦‹

this is lowkey the best part. These new YANG statements give you way more access control granularity than top-level rpc and notification statements do. The new action and notification statements sit within data nodes, and you can restrict access to an action or notification down to specific instances of those data nodes πŸŽ€

RESTCONF support has been added too 🌈 The RESTCONF operations are pretty similar to the NETCONF operations, so mapping them onto the existing NACM procedures and data model is totally doable ✨

The data node access behavior for path matches got clarified. It now also covers matching descendant nodes of the specified path πŸ“

The <edit-config> operation access rights behavior also got a clarification πŸ’… Write access is not required for data nodes that are implicitly modified through side effects. Examples are the evaluation of YANG when-stmts, or data nodes that get implicitly deleted when you create a data node under a different branch of a YANG choice-stmt 🧚

The Security Considerations section was updated to comply with the "YANG module security guidelines" [YANG-SEC] πŸ”₯ Also, the YANG module in this document does not define any RPC operations, so no notes there, bestie 🫢

2. Access Control Design Objectives πŸ‘‘

this section documents the design objectives for the NETCONF access control model presented in Section 3 πŸŽ€

2.1. Access Control Points πŸ¦‹

NETCONF lets server implementers add new custom protocol operations, and the YANG data modeling language supports this feature ✨ These operations can be defined in standard or proprietary YANG modules.

it is not possible to design an ACM for NETCONF that only focuses on a static set of standard protocol operations defined by NETCONF itself, unlike some other protocols 😭 Since few assumptions can be made about an arbitrary protocol operation, the NETCONF architectural server components need to be protected at three conceptual control points πŸ’€

these access control points, shown in Figure 1, are:

  • protocol operation: Permission to invoke specific protocol operations.
  • datastore: Permission to read and/or alter specific data nodes within any datastore.
  • notification: Permission to receive specific notification event types.
             +-------------+                 +-------------+
client       |  protocol   |                 |  data node  |
request -->  |  operation  | ------------->  |   access    |
             |  allowed?   |   datastore     |  allowed?   |
             +-------------+   or state      +-------------+
                               data access


             +----------------+
             |  notification  |
event -->    |  allowed?      |
             +----------------+

                             Figure 1

2.2. Simplicity 🌸

there is concern that a complicated ACM won't be widely deployed because it's too hard to use πŸ™ˆ Configuration of the access control system needs to be as simple as possible. Simple and common tasks need to be easy to configure and should require little expertise or domain-specific knowledge. Complex tasks are possible using additional mechanisms that may require additional expertise.

a single set of access control rules ought to be able to control all types of NETCONF protocol operation invocation, all datastore access, and all notification events 🫢

access control ought to be defined with a small and familiar set of permissions, while still allowing full control of datastore access πŸ’…

2.3. Procedural Interface 🧚

NETCONF uses a Remote Procedure Call (RPC) model and an extensible set of protocol operations. Access control for any possible protocol operation is necessary πŸ”₯

2.4. Datastore Access πŸ’œ

it's necessary to control access to specific nodes and subtrees within the datastore, regardless of which protocol operation (standard or proprietary) was used to access the datastore ✨

2.5. Users and Groups πŸ‘‘

it's necessary that access control rules for a single user, or for a configurable group of users, can be configured πŸ’–

the ACM needs to support the concept of administrative groups, so it can make the well-established distinction between a root account and other types of less-privileged conceptual user accounts 🌈 These groups need to be configurable by the administrator.

it's necessary that the user-to-group mapping can be delegated to a central server, such as a RADIUS server [RFC2865] [RFC5607] πŸ¦‹ Since authentication is performed by the transport layer, and RADIUS performs authentication and service authorization at the same time, the underlying transport protocol needs to be able to report a set of group names associated with the user to the server. It's necessary that the administrator can disable the usage of these group names within the ACM πŸ™…β€β™€οΈ

2.6. Maintenance πŸŽ€

it ought to be possible to disable part or all of the access control model enforcement procedures without deleting any access control rules πŸ“

2.7. Configuration Capabilities 🌈

suitable configuration and monitoring mechanisms are needed so an administrator can easily manage all aspects of the ACM's behavior ⭐ A standard data model, suitable for use with the <edit-config> protocol operation, needs to be available for this purpose.

access control rules that restrict access operations on specific subtrees within the configuration datastore need to be supported πŸ”₯

2.8. Identifying Security-Sensitive Content πŸ’€

one of the most important aspects of the data model documentation, and one of the biggest concerns during deployment, is identifying security-sensitive content 😭 This applies to protocol operations in NETCONF, not just to data and notifications.

it is mandatory for security-sensitive objects to be documented in the Security Considerations section of an RFC. This is nice, but it is not good enough, for the following reasons:

  • This documentation-only approach forces administrators to study the RFC and determine if there are any potential security risks introduced by a new data model.
  • If any security risks are identified, then the administrator must study some more RFC text and determine how to mitigate the security risk(s).
  • The ACM on each server must be configured to mitigate the security risks, e.g., require privileged access to read or write the specific data identified in the Security Considerations section.
  • If the ACM is not preconfigured, then there will be a time window of vulnerability after the new data model is loaded and before the new access control rules for that data model are configured, enabled, and debugged 😱

often, the administrator just wants to disable default access to the secure content so that no inadvertent or malicious changes can be made to the server πŸ”’ This allows the default rules to be more lenient, without significantly increasing the security risk ✨

a data model designer needs to be able to use machine-readable statements to identify content that needs to be protected by default πŸ¦‹ This will allow client and server tools to automatically identify data-model-specific security risks, by denying access to sensitive data unless the user is explicitly authorized to perform the requested access operation 🫢

3. NETCONF Access Control Model (NACM) πŸ’–

3.1. Overview 🌈

this section gives a high-level overview of the access control model structure 🧚 It describes the NETCONF protocol message processing model and the conceptual access control requirements within that model.

3.1.1. Features ✨

the NACM data model provides the following features:

  • Independent control of RPC, action, data, and notification access is provided.
  • The concept of an emergency recovery session is supported, but configuration of the server for this purpose is beyond the scope of this document. An emergency recovery session will bypass all access control enforcement, so it can initialize or repair the NACM configuration πŸš‘
  • A simple and familiar set of datastore permissions is used.
  • Support for YANG security tagging (e.g., a nacm:default-deny-write statement) allows default security modes to automatically exclude sensitive data πŸ”
  • Separate default access modes for read, write, and execute permissions are provided.
  • Access control rules are applied to configurable groups of users.
  • The access control enforcement procedures can be disabled during operation, without deleting any access control rules, in order to debug operational problems πŸ› οΈ
  • The number of denied protocol operation requests and denied datastore write requests can be monitored by the client πŸ‘€
  • Simple unconstrained YANG instance-identifiers are used to configure access control rules for specific data nodes πŸ’…

3.1.2. External Dependencies 🌸

NETCONF [RFC6241] and RESTCONF [RFC8040] are used for network management purposes within this document πŸ“

the YANG data modeling language [RFC7950] is used to define the data models for use with NETCONF or RESTCONF. YANG is also used to define the data model in this document πŸŽ€

3.1.3. Message Processing Model πŸ¦‹

okay so this is where we get to see the whole conceptual message flow, bestie πŸ’… the diagram shows exactly where access control kicks in while NETCONF messages are getting processed. no cap, it's giving architecture glow-up ✨

RESTCONF operations get mapped onto the access control model based on the HTTP method and the resource class being used. so like, a POST on a data resource counts as "write data node" access, but a POST on an operation resource counts as "operation" access. the way that the method + resource type decides the permission is literally so iconic πŸŽ€

the new "pre-read data node acc. ctl" boxes in the diagram 🌸 are about group read access for the data node ancestors of an action or notification. example time: if an action is defined as /interfaces/interface/reset-interface, then the group has to be authorized to (1) read /interfaces and /interfaces/interface and (2) execute on /interfaces/interface/reset-interface. obsessed with how thorough that is 😭

                    +-------------------------+
                    |       session           |
                    |      (username)         |
                    +-------------------------+
                       |                 ^
                       V                 |
             +--------------+     +---------------+
             |   message    |     |   message     |
             | dispatcher   |     |   generator   |
             +--------------+     +---------------+
               |      |               ^         ^
               |      V               |         |
               |  +=============+     |         |
               |  | pre-read    |     |         |
               |  | data node   |     |         |
               |  | acc. ctl    |     |         |
               |  +=============+     |         |
               |    |                 |         |
               V    V                 |         |
         +===========+     +-------------+   +----------------+
         | operation |---> |    reply    |   | <notification> |
         | acc. ctl  |     |  generator  |   |  generator     |
         +===========+     +-------------+   +----------------+
               |              ^    ^                ^
               V       +------+    |                |
         +-----------+ |   +=============+  +================+
         | operation | |   |    read     |  | <notification> |
         | processor |-+   | data node   |  |  access ctl    |
         |           |     | acc. ctl    |  |                |
         +-----------+     +=============+  +================+
               |   |                  ^       ^     ^
               V   +----------------+ |       |     |
         +===========+              | |       | +============+
         |  write    |              | |       | | pre-read   |
         | data node |              | |       | | data node  |
         | acc. ctl  | -----------+ | |       | | acc. ctl   |
         +===========+            | | |       | +============+
               |                  | | |       |   ^
               V                  V V |       |   |
         +---------------+      +-------------------+
         | configuration | ---> |      server       |
         |   datastore   |      |  instrumentation  |
         |               | <--- |                   |
         +---------------+      +-------------------+

                                 Figure 2

okay so this next bit is the big checklist for every received <rpc> message, but only if access control enforcement is turned on πŸ”₯

  • for each active session, access control gets applied individually to all <rpc> messages (except <close-session>) the server receives, unless the session is identified as a recovery session πŸ™ˆ
  • if the <action> operation from [RFC7950] gets invoked, then read access is required for ALL the instances in the data node hierarchy that identifies the specific action in the datastore, AND execute access is required for the action node. if the user isn't authorized to read all the specified data nodes and execute the action, the request gets rejected with an "access-denied" error πŸ’€
  • otherwise, if the user isn't authorized to execute the specified protocol operation, the request gets rejected with an "access-denied" error 🫢
  • if a datastore is accessed by the protocol operation, the server checks whether the client is authorized to access the nodes in the datastore. if the user isn't authorized to perform the requested access operation on the requested data, the request gets rejected with an "access-denied" error ✨

and for each generated notification event, if access control enforcement is enabled, here's the flow 🌈

  • server instrumentation generates a notification for a particular subscription πŸ¦‹
  • if the "notification" statement is specified within a data subtree (as specified in [RFC7950]), then read access is required for all instances in the data node hierarchy that identifies the specific notification in the datastore, and read access is required for the notification node too. if the user isn't authorized to read all the specified data nodes and the notification node, the notification gets dropped for that subscription 😭
  • if the "notification" statement is a top-level statement, the notification access control enforcer checks the notification event type, and if it's one the user isn't authorized to read, the notification gets dropped for that subscription πŸ’œ

3.2. Datastore Access πŸ’–

the same access control rules apply to all datastores that support the NACM. for example, the candidate configuration datastore or the running configuration datastore πŸŽ€

all conventional configuration datastores and the operational state datastore are controlled by the NACM. local files, remote files, or datastores accessed via the <url> parameter are NOT controlled by the NACM πŸ™…β€β™€οΈ

3.2.1. Mapping New Datastores to NACM 🧚

it's possible new datastores will get defined over time for use with NETCONF. the NACM MAY be applied to other datastores that have similar access rights as defined in the NACM. to apply the NACM to a new datastore, the new datastore specification needs to define how it maps to the NACM CRUDX (Create, Read, Update, Delete, eXec) access rights. it's possible that only a subset of the NACM access rights would be applicable. for example, only retrieval access control would be needed for a read-only datastore. operations and access rights not supported by the NACM CRUDX model are outside the scope of this document. a datastore does NOT need to use the NACM, e.g., the datastore specification defines something else or doesn't use access control 🌸

3.2.2. Access Rights πŸ“

a small set of hard-wired datastore access rights is needed to control access to all possible protocol operations, including vendor extensions to the standard protocol operation set πŸ‘‘

the CRUDX model can support all protocol operations:

  • Create: allows the client to add a new data node instance to a datastore 🌟
  • Read: allows the client to read a data node instance from a datastore or receive the notification event type πŸ‘€
  • Update: allows the client to update an existing data node instance in a datastore ✏️
  • Delete: allows the client to delete a data node instance from a datastore πŸ—‘οΈ
  • eXec: allows the client to execute the operation ⚑

3.2.3. RESTCONF Methods 🌈

RESTCONF uses HTTP methods to perform datastore operations, kinda like NETCONF does. the NACM procedures were originally written for NETCONF protocol operations, so RESTCONF methods get mapped to NETCONF operations for access control processing. the enforcement procedures in this document apply to both protocols unless explicitly stated otherwise 🫢

the request URI needs to be considered when processing RESTCONF requests on data resources:

  • for HEAD and GET requests, any data nodes that are ancestor nodes of the target resource are considered part of the retrieval request for access control purposes πŸ”
  • for PUT, PATCH, and DELETE requests, any data nodes that are ancestor nodes of the target resource are NOT considered part of the edit request for access control purposes. the access operation for these nodes is considered to be "none". the edit begins at the target resource 🎯
  • for POST requests on data resources, any data nodes specified in the request URI (including the target resource) are NOT considered part of the edit request for access control purposes. the access operation for these nodes is considered to be "none". the edit begins at a child node of the target resource, specified in the message body πŸ’…

not all RESTCONF methods are subject to access control. the table below shows how each method maps to NETCONF protocol operations. the value "none" means the NACM isn't applied at all to that RESTCONF method πŸ™ˆ

+---------+-----------------+---------------------+-----------------+
| Method  | Resource class  | NETCONF operation   | Access          |
|         |                 |                     | operation       |
+---------+-----------------+---------------------+-----------------+
| OPTIONS | all             | none                | none            |
| HEAD    | all             | <get>, <get-config> | read            |
| GET     | all             | <get>, <get-config> | read            |
| POST    | datastore, data | <edit-config>       | create          |
| POST    | operation       | specified operation | execute         |
| PUT     | data            | <edit-config>       | create, update  |
| PUT     | datastore       | <copy-config>       | update          |
| PATCH   | data, datastore | <edit-config>       | update          |
| DELETE  | data            | <edit-config>       | delete          |
+---------+-----------------+---------------------+-----------------+

            Table 1: Mapping RESTCONF Methods to NETCONF

3.2.4. <get> and <get-config> Operations πŸŽ€

the NACM access rights aren't directly coupled to the <get> and <get-config> protocol operations, but they apply to all <rpc> operations that would result in a "read" access operation to the target datastore. this section describes how these access rights apply to the specific access operations supported by the <get> and <get-config> protocol operations πŸ¦‹

data nodes the client doesn't have read access to are silently omitted, along with any descendants, from the <rpc-reply> message. this is done so NETCONF filters for <get> and <get-config> keep working properly, instead of causing an "access-denied" error because the filter criteria would otherwise include unauthorized read access to some data nodes. for NETCONF filtering purposes, the selection criteria get applied to the subset of nodes the user is authorized to read, NOT the entire datastore ✨

3.2.5. <edit-config> Operation ✨

okay so NACM access rights are NOT directly tied to the <edit-config> "operation" attribute πŸ™ˆ they're similar vibes, but not the same thing. A NACM access right applies to every protocol operation that would result in a particular access operation on the target datastore. this section is about how those access rights hit the specific access operations that <edit-config> can do πŸ’…

if the effective access operation is none (aka default-operation="none") for a data node, then NO access control is applied to that node 🫢 this is required so you can get into a subtree inside a bigger structure. like, a user might be allowed to create a new /interfaces/interface list entry but NOT allowed to create or delete the parent container (/interfaces) 😭 if /interfaces already exists in the target datastore, the effective operation for the /interfaces node is none when you edit an /interfaces/interface list entry. the girl gets her moment without touching the parent πŸŽ€

if the protocol operation would create a datastore node and the user does NOT have "create" access permission for that node, the operation gets rejected with an "access-denied" error 🚫

if the protocol operation would delete a datastore node and the user does NOT have "delete" access permission for that node, the operation gets rejected with an "access-denied" error 🚫

if the protocol operation would modify a datastore node and the user does NOT have "update" access permission for that node, the operation gets rejected with an "access-denied" error 🚫

a "merge" or "replace" <edit-config> operation can include data nodes that don't actually change anything in the datastore πŸ¦‹ like, a container or list node might just be there for naming purposes. those unaltered nodes get ignored by the server and don't need any access rights from the client, so no stress bestie 🌸

a "merge" <edit-config> operation can also leave out particular child data nodes that ARE in the datastore 🧚 those missing nodes, within the scope of the "merge", get ignored by the server and don't need any access rights from the client either ✨

the contents of specific restricted datastore nodes MUST NOT be exposed in any <rpc-error> elements within the reply πŸ™Š this is a big deal, so keep it locked down, no leaking the secret stuff in error messages πŸ”’

an <edit-config> operation can cause data nodes to be implicitly created or deleted as a side effect of what was requested ✨ for example, a YANG when-stmt expression might evaluate to a different result, which can delete nodes or create them with default values. or if a data node gets created under one branch of a YANG choice-stmt, then all the data nodes under the OTHER branches get implicitly removed πŸ’€ the main point: NO NACM access rights are required on any data nodes that change implicitly as a side effect of another allowed operation. the side effects are free, lowkey iconic πŸ‘‘

3.2.6. <copy-config> Operation πŸ“

access control for the <copy-config> protocol operation needs special care, because the admin might be replacing the ENTIRE target datastore 😳 that's a lot of power in one move.

if the source of <copy-config> is the running configuration datastore and the target is the startup configuration datastore, the client only needs permission to execute the <copy-config> protocol operation πŸ’–

otherwise:

  • if the source of the <copy-config> operation is a datastore, then data nodes the client doesn't have read access to are silently omitted πŸ™ˆ
  • if the target of the <copy-config> operation is a datastore, the client needs access to the modified nodes. specifically:
    • if the protocol operation would create a datastore node and the user does NOT have "create" access permission for that node, the operation is rejected with an "access-denied" error 🚫
    • if the protocol operation would delete a datastore node and the user does NOT have "delete" access permission for that node, the operation is rejected with an "access-denied" error 🚫
    • if the protocol operation would modify a datastore node and the user does NOT have "update" access permission for that node, the operation is rejected with an "access-denied" error 🚫

3.2.7. <delete-config> Operation πŸ—‘οΈ

access to the <delete-config> protocol operation is denied by default πŸ™…β€β™€οΈ the "exec-default" leaf does NOT apply to this one. you have to explicitly configure access control rules to let a non-recovery session invoke it. no vibes, only rules πŸ’…

3.2.8. <commit> Operation 🌈

the server MUST figure out the exact nodes in the running configuration datastore that are actually different, and then ONLY check "create", "update", and "delete" access permissions for that set of nodes. that set could even be empty, and that's totally valid 🫧

for example, if a session can read the whole datastore but can only change one leaf, that session needs to be able to edit AND commit that one leaf. so it's giving "exactly what you need, nothing more" 🎯

3.2.9. <discard-changes> Operation πŸ¦‹

the client only needs permission to execute the <discard-changes> protocol operation ✨ no datastore permissions are needed. easy breezy 🌸

3.2.10. <kill-session> Operation ⚠️

the <kill-session> operation doesn't directly alter a datastore πŸ™ƒ BUT it lets one session disrupt another session that's editing a datastore, so it's not nothing, bestie πŸ‘€

access to the <kill-session> protocol operation is denied by default πŸ™…β€β™€οΈ the "exec-default" leaf does NOT apply to this one either. access control rules must be explicitly configured to let a non-recovery session invoke it.


3.3. Model Components 🧩

this section defines the conceptual components that make up the access control model. it's the cast of characters, and the plot is coming 🎬

3.3.1. Users πŸ‘€

a "user" is the conceptual entity that's tied to the access permissions granted to a particular session πŸ’œ a user is identified by a string that's unique within the server.

as described in [RFC6241], the username string is derived from the transport layer during session establishment πŸ” if the transport layer can't authenticate the user, the session is terminated. no auth, no entry, periodt πŸšͺ

3.3.2. Groups πŸ‘―

access to a specific NETCONF protocol operation is granted to a session. the session is associated with a group (NOT with a user) 🫢

a group is identified by its name, and all group names are unique within the server ✨

access control gets applied at the level of groups. a group contains zero or more group members 🌷

a group member is identified by a username string πŸ’…

the same user can be a member of multiple groups. main character energy πŸ‘‘

3.3.3. Emergency Recovery Session 🚨

the server MAY support a recovery session mechanism, which bypasses ALL access control enforcement πŸ”“ this is useful for restricting initial access and repairing a broken access control configuration. it's the emergency exit, bestie, so you're never locked out of your own house 🏠

3.3.4. Global Enforcement Controls πŸŽ›οΈ

there are five global controls that help decide how access control gets enforced. think of them as the mood dials 🎚️

3.3.4.1. enable-nacm Switch βœ…

a global "enable-nacm" on/off switch enables or disables ALL access control enforcement πŸ’‘ when this global switch is set to "true", every request is checked against the access control rules, and it's only permitted if the rules allow that specific access request. when it's set to "false", every access request is permitted. it's the master switch, lowkey the most important one 🫧

3.3.4.2. read-default Switch πŸ“–

an on/off "read-default" switch enables or disables default access to receive data in replies and notifications πŸ’Œ this one matters when the "enable-nacm" global switch is "true" AND no matching access control rule explicitly permits or denies read access to the requested datastore data or notification event type πŸ€”

when this global switch is set to "permit" and no matching access control rule is found for the datastore read or notification event requested, access is permitted 🟒

when this global switch is set to "deny" and no matching access control rule is found for the datastore read or notification event requested, access is denied πŸ”΄ that means the requested data is NOT sent to the client. see step 11 in Section 3.4.5 for details πŸ“

3.3.4.3. write-default Switch ✍️

an on/off "write-default" switch enables or disables default access to alter configuration data πŸ› οΈ when the "enable-nacm" global switch is "true", this one matters if no matching access control rule explicitly permits or denies write access to the requested datastore data.

when this global switch is set to "permit" and no matching access control rule is found for the datastore write requested, access is permitted 🟒

when this global switch is set to "deny" and no matching access control rule is found for the datastore write requested, access is denied πŸ”΄ see step 12 in Section 3.4.5 for details πŸ“

3.3.4.4. exec-default Switch πŸš€

an on/off "exec-default" switch enables or disables default access to execute protocol operations ⚑ when the "enable-nacm" global switch is "true", this one matters if no matching access control rule explicitly permits or denies access to the requested NETCONF protocol operation.

when this global switch is set to "permit" and no matching access control rule is found for the NETCONF protocol operation requested, access is permitted 🟒

when this global switch is set to "deny" and no matching access control rule is found for the NETCONF protocol operation requested, access is denied πŸ”΄ see step 12 in Section 3.4.4 and step 13 in Section 3.4.5 for details πŸ“

3.3.4.5. enable-external-groups Switch 🌍

when this global switch is set to "true", the group names reported by the transport layer for a session are used together with the locally configured group names to figure out the access control rules for that session 🀝

when this switch is set to "false", the group names reported by the transport layer are ignored by the NACM πŸ™…β€β™€οΈ

3.3.5. Access Control Rules πŸ“œ

there are four types of rules available in the NACM πŸ—‚οΈ

  • module rule: controls access for definitions in a specific YANG module, identified by its name πŸ“¦
  • protocol operation rule: controls access for a specific protocol operation, identified by its YANG module and name βš™οΈ
  • data node rule: controls access for a specific data node and its descendants, identified by its path location within the conceptual XML document for the data node 🌳
  • notification rule: controls access for a specific notification event type, identified by its YANG module and name πŸ””

3.4. Access Control Enforcement Procedures πŸ›‘οΈ

there are six separate phases that need to be addressed, and four of them are related to the NETCONF message processing model (Section 3.1.3) 🧠

  1. Initial operation πŸŒ…
  2. Session establishment 🀝
  3. "access-denied" error handling πŸ™…β€β™€οΈ
  4. Incoming RPC message validation πŸ“¬
  5. Data node access validation πŸ”
  6. Outgoing <notification> authorization πŸ“£

in addition, the initial startup mode for a NETCONF server, session establishment, and "access-denied" error-handling procedures also need to be considered ✨

the server MUST use the access control rules in effect at the time it starts processing the message πŸ•°οΈ and those SAME access control rules MUST stay in effect for the processing of the entire message. no mid-message rule swaps, that's the rule πŸ”’πŸ’–

3.4.1. Initial Operation

okay so the very first time a NETCONF server boots up 🌸, the access control configuration will probably not be there yet πŸ™ˆ. If it isn't, a server MUST NOT allow any write access to any session role except a recovery session. no exceptions, bestie πŸ”’

Access rules get enforced any time a request is kicked off from a user session πŸ’…. Access control is not enforced for server-initiated access requests, like the initial load of the running configuration datastore during bootup ✨.

3.4.2. Session Establishment

the access control model only cares about the well-formed XML content that gets passed between a client and a server after session establishment is done and after the <hello> exchange has finished successfully πŸ¦‹.

once the session is set up and the user is authenticated, the transport layer hands the username and a possibly empty set of group names over to the NETCONF server πŸŽ€. then the server enforces the access control rules using that username, those group names, and the configuration data stored on the server. main character energy from the server, honestly πŸ‘‘

3.4.3. "access-denied" Error Handling

the access-denied error-tag shows up when the access control system says no to either a request to invoke a protocol operation or a request to do a particular access operation on the configuration datastore 🚫.

A server MUST NOT include any information the client is not allowed to read in any <error-info> elements within the <rpc-error> response. this is a big deal, so don't leak anything in the error response πŸ’€

3.4.4. Incoming RPC Message Validation

this diagram is the basic vibe of how access control processing works for incoming NETCONF <rpc> messages inside a server 🧚

          NETCONF server
          +------------+
          |    XML     |
          |   message  |
          | dispatcher |
          +------------+
                 |
                 |
                 V
         +---------------+
         | <rpc> message |
         +---------------+
           |    |     |
           |    |     +--------------------------------+
           |    +---------------+                      |
           V                    V                      V
 +------------------+ +--------------------+ +--------------------+
 | vendor operation | | standard operation | | standard operation |
 |    <my-edit>     | |   <edit-config>    | |      <unlock>      |
 +------------------+ +--------------------+ +--------------------+
             |                 |
             |                 |
             V                 V
            +----------------------+
            |    configuration     |
            |      datastore       |
            +----------------------+

                             Figure 3

access control starts at the message dispatcher πŸ“¬.

after the server validates the <rpc> element and figures out the namespace URI and the element name of the protocol operation being requested, it checks that the user is authorized to invoke that operation πŸ”.

the server MUST separately authorize every protocol operation by following these steps βœ…:

  1. If the enable-nacm leaf is set to false, then the protocol operation is permitted.
  2. If the requesting session is identified as a recovery session, then the protocol operation is permitted.
  3. If the requested operation is the NETCONF <close-session> protocol operation, then the protocol operation is permitted.
  4. Check all the group entries to see if any of them contain a user-name entry that equals the username for the session making the request. If the enable-external-groups leaf is true, add to these groups the set of groups provided by the transport layer.
  5. If no groups are found, continue with step 10.
  6. Process all rule-list entries, in the order they appear in the configuration. If a rule-list's group leaf-list does not match any of the user's groups, proceed to the next rule-list entry.
  7. For each rule-list entry found, process all rules, in order, until a rule that matches the requested access operation is found. A rule matches if all of the following criteria are met:
    • The rule's module-name leaf is * or equals the name of the YANG module where the protocol operation is defined.
    • Either (1) the rule does not have a rule-type defined or (2) the rule-type is protocol-operation and the rpc-name is * or equals the name of the requested protocol operation.
    • The rule's access-operations leaf has the exec bit set or has the special value *.
  8. If a matching rule is found, then the action leaf is checked. If it is equal to permit, then the protocol operation is permitted; otherwise, it is denied.
  9. At this point, no matching rule was found in any rule-list entry.
  10. If the requested protocol operation is defined in a YANG module advertised in the server capabilities and the rpc statement contains a nacm:default-deny-all statement, then the protocol operation is denied.
  11. If the requested protocol operation is the NETCONF <kill-session> or <delete-config>, then the protocol operation is denied.
  12. If the exec-default leaf is set to permit, then permit the protocol operation; otherwise, deny the request.

if the user is NOT authorized to invoke the protocol operation, an <rpc-error> gets generated with this info 😀:

error-tag: access-denied

error-path: identifies the requested protocol operation. the example below is for the <edit-config> protocol operation in the NETCONF base namespace πŸ“:

         <error-path
           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
             /nc:rpc/nc:edit-config
         </error-path>

if a datastore is accessed, either directly or as a side effect of the protocol operation, then the server MUST intercept the access operation and make sure the user is authorized to perform the requested access operation on the specified data, as defined in Section 3.4.5 πŸ’œ.

3.4.5. Data Node Access Validation

if (1) a data node within a datastore is accessed or (2) an action or notification is tied to a data node, then the server MUST ensure that the user is authorized to perform the requested "read", "create", "update", "delete", or "execute" access operation on the specified data node 🌈.

if an action is requested to be executed, the server MUST ensure that the user is authorized to perform the "execute" access operation on the requested action πŸ”₯.

if a notification tied to a data node is generated, the server MUST ensure that the user is authorized to perform the "read" access operation on the requested notification ✨.

the data node access request gets authorized by following these steps 🫢:

  1. If the enable-nacm leaf is set to false, then the access operation is permitted.
  2. If the requesting session is identified as a recovery session, then the access operation is permitted.
  3. Check all the group entries to see if any of them contain a user-name entry that equals the username for the session making the request. If the enable-external-groups leaf is true, add to these groups the set of groups provided by the transport layer.
  4. If no groups are found, continue with step 9.
  5. Process all rule-list entries, in the order they appear in the configuration. If a rule-list's group leaf-list does not match any of the user's groups, proceed to the next rule-list entry.
  6. For each rule-list entry found, process all rules, in order, until a rule that matches the requested access operation is found. A rule matches if all of the following criteria are met:
    • The rule's module-name leaf is * or equals the name of the YANG module where the requested data node is defined.
    • Either (1) the rule does not have a rule-type defined or (2) the rule-type is data-node and the path matches the requested data node, action node, or notification node. A path is considered to match if the requested node is the node specified by the path or is a descendant node of the path.
    • For a "read" access operation, the rule's access-operations leaf has the "read" bit set or has the special value *.
    • For a "create" access operation, the rule's access-operations leaf has the "create" bit set or has the special value *.
    • For a "delete" access operation, the rule's access-operations leaf has the "delete" bit set or has the special value *.
    • For an "update" access operation, the rule's access-operations leaf has the "update" bit set or has the special value *.
    • For an "execute" access operation, the rule's access-operations leaf has the "exec" bit set or has the special value *.
  7. If a matching rule is found, then the action leaf is checked. If it is equal to permit, then the data node access is permitted; otherwise, it is denied. For a "read" access operation, "denied" means that the requested data is not returned in the reply.
  8. At this point, no matching rule was found in any rule-list entry.
  9. For a "read" access operation, if the requested data node is defined in a YANG module advertised in the server capabilities and the data definition statement contains a nacm:default-deny-all statement, then the requested data node and all its descendants are not included in the reply.
  10. For a "write" access operation, if the requested data node is defined in a YANG module advertised in the server capabilities and the data definition statement contains a nacm:default-deny-write or a nacm:default-deny-all statement, then the access request is denied for the data node and all its descendants.
  11. For a "read" access operation, if the read-default leaf is set to permit, then include the requested data node in the reply; otherwise, do not include the requested data node or any of its descendants in the reply.
  12. For a "write" access operation, if the write-default leaf is set to permit, then permit the data node access request; otherwise, deny the request.
  13. For an "execute" access operation, if the exec-default leaf is set to permit, then permit the request; otherwise, deny the request.

that's the whole access control enforcement flow, bestie πŸŽ€ more parts coming, so stay with me πŸ’–

3.4.6. Outgoing <notification> Authorization

okay so, bestie, anything about access rules for descendant nodes of a notification event type is out of scope here πŸ™ˆ but the big vibe is: if you're allowed to receive the notification event type, you're automatically allowed to receive whatever data it carries πŸ’–

if the notification is defined inside a data subtree (per [RFC7950]), then you need read access to the notification itself. then processing carries on the way we covered in Section 3.4.5 🫢

here's the conceptual message processing model for outgoing <notification> messages, and it's giving layers 🧚

                          NETCONF server
                         +------------+
                         |    XML     |
                         |   message  |
                         | generator  |
                         +------------+
                               ^
                               |
                       +----------------+
                       | <notification> |
                       |  generator     |
                       +----------------+
                               ^
                               |
                      +=================+
                      | <notification>  |
                      |  access control |
                      |  <eventType>    |
                      +=================+
                               ^
                               |
                   +------------------------+
                   | server instrumentation |
                   +------------------------+
                             |     ^
                             V     |
                    +----------------------+
                    |    configuration     |
                    |      datastore       |
                    +----------------------+

                            Figure 4

so, to check whether a generated notification for a specific subscription [RFC5277] is authorized, you go through these steps, in this exact order πŸ’…

  1. If the "enable-nacm" leaf is set to "false", the notification is permitted. easy win 🌸
  2. If the session is a recovery session, the notification is permitted πŸ¦‹
  3. If the notification is the NETCONF <replayComplete> or <notificationComplete> event type [RFC5277], the notification is permitted ✨
  4. Look at all the "group" entries and see if any of them have a "user-name" entry that matches the username of the session making the request. If the "enable-external-groups" leaf is "true", add the groups the transport layer provides to these groups too πŸ‘‘
  5. If no groups are found, skip ahead to step 10 😭
  6. Go through all the rule-list entries, in the order they show up in the configuration. If a rule-list's "group" leaf-list doesn't match any of the user's groups, move on to the next rule-list entry πŸŽ€
  7. For each rule-list entry you found, go through all the rules, in order, until you find one that matches the requested access operation. A rule matches only if all of these are true πŸ’œ
    • The rule's "module-name" leaf is "*" or equals the name of the YANG module where the notification is defined.
    • Either (1) the rule doesn't have a "rule-type" defined, or (2) the "rule-type" is "notification" and the "notification-name" is "*" or equals the name of the notification.
    • The rule's "access-operations" leaf has the "read" bit set, or has the special value "*".
  8. If you found a matching rule, check the "action" leaf. If it's equal to "permit", permit the notification. Otherwise, drop the notification for the associated subscription πŸ”₯
  9. Otherwise, no matching rule was found in any rule-list entry πŸ™ˆ
  10. If the requested notification is defined in a YANG module that's advertised in the server capabilities, and the "notification" statement has a nacm:default-deny-all statement, drop the notification for the associated subscription πŸ’€
  11. If the "read-default" leaf is set to "permit", permit the notification. Otherwise, drop the notification for the associated subscription 🌈

3.5. Data Model Definitions

3.5.1. Data Organization

this diagram is the tea on what's inside the NACM YANG module and how it's structured β˜•

module: ietf-netconf-acm
  +--rw nacm
     +--rw enable-nacm?              boolean
     +--rw read-default?             action-type
     +--rw write-default?            action-type
     +--rw exec-default?             action-type
     +--rw enable-external-groups?   boolean
     +--ro denied-operations         yang:zero-based-counter32
     +--ro denied-data-writes        yang:zero-based-counter32
     +--ro denied-notifications      yang:zero-based-counter32
     +--rw groups
     |  +--rw group* [name]
     |     +--rw name         group-name-type
     |     +--rw user-name*   user-name-type
     +--rw rule-list* [name]
        +--rw name     string
        +--rw group*   union
        +--rw rule* [name]
           +--rw name                 string
           +--rw module-name?         union
           +--rw (rule-type)?
           |  +--:(protocol-operation)
           |  |  +--rw rpc-name?            union
           |  +--:(notification)
           |  |  +--rw notification-name?   union
           |  +--:(data-node)
           |     +--rw path                 node-instance-identifier
           +--rw access-operations?   union
           +--rw action               action-type
           +--rw comment?             string

3.5.2. YANG Module

this part is the normative stuff 🫢 the following YANG module specifies the NETCONF content that MUST be supported by the server, so it's non-negotiable bestie 😀

the "ietf-netconf-acm" YANG module imports typedefs from [RFC6991] ✨

<CODE BEGINS> file "ietf-netconf-acm@2018-02-14.yang"

module ietf-netconf-acm {

  namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm";

  prefix nacm;

  import ietf-yang-types {
    prefix yang;
  }

  organization
    "IETF NETCONF (Network Configuration) Working Group";

  contact
    "WG Web:   <https://datatracker.ietf.org/wg/netconf/>
     WG List:  <mailto:netconf@ietf.org>

     Author:   Andy Bierman
               <mailto:andy@yumaworks.com>

     Author:   Martin Bjorklund
               <mailto:mbj@tail-f.com>";

  description
    "Network Configuration Access Control Model.

     Copyright (c) 2012 - 2018 IETF Trust and the persons
     identified as authors of the code.  All rights reserved.

     Redistribution and use in source and binary forms, with or
     without modification, is permitted pursuant to, and subject
     to the license terms contained in, the Simplified BSD
     License set forth in Section 4.c of the IETF Trust's
     Legal Provisions Relating to IETF Documents
     (https://trustee.ietf.org/license-info).

     This version of this YANG module is part of RFC 8341; see
     the RFC itself for full legal notices.";

  revision "2018-02-14" {
    description
      "Added support for YANG 1.1 actions and notifications tied to
       data nodes.  Clarified how NACM extensions can be used by
       other data models.";
    reference
      "RFC 8341: Network Configuration Access Control Model";
  }

  revision "2012-02-22" {
    description
      "Initial version.";
    reference
      "RFC 6536: Network Configuration Protocol (NETCONF)
                 Access Control Model";
  }

  /*
   * Extension statements
   */

  extension default-deny-write {
    description
      "Used to indicate that the data model node
       represents a sensitive security system parameter.

       If present, the NETCONF server will only allow the designated
       'recovery session' to have write access to the node.  An
       explicit access control rule is required for all other users.

       If the NACM module is used, then it must be enabled (i.e.,
       /nacm/enable-nacm object equals 'true'), or this extension
       is ignored.

       The 'default-deny-write' extension MAY appear within a data
       definition statement.  It is ignored otherwise.";
  }

  extension default-deny-all {
    description
      "Used to indicate that the data model node
       controls a very sensitive security system parameter.

       If present, the NETCONF server will only allow the designated
       'recovery session' to have read, write, or execute access to
       the node.  An explicit access control rule is required for all
       other users.

       If the NACM module is used, then it must be enabled (i.e.,
       /nacm/enable-nacm object equals 'true'), or this extension
       is ignored.

       The 'default-deny-all' extension MAY appear within a data
       definition statement, 'rpc' statement, or 'notification'
       statement.  It is ignored otherwise.";
  }

  /*
   * Derived types
   */

  typedef user-name-type {
    type string {
      length "1..max";
    }
    description
      "General-purpose username string.";
  }

  typedef matchall-string-type {
    type string {
      pattern '\*';
    }
    description
      "The string containing a single asterisk '*' is used
       to conceptually represent all possible values
       for the particular leaf using this data type.";
  }

  typedef access-operations-type {
    type bits {
      bit create {
        description
          "Any protocol operation that creates a
           new data node.";
      }
      bit read {
        description
          "Any protocol operation or notification that
           returns the value of a data node.";
      }
      bit update {
        description
          "Any protocol operation that alters an existing
           data node.";
      }
      bit delete {
        description
          "Any protocol operation that removes a data node.";
      }
      bit exec {
        description
          "Execution access to the specified protocol operation.";
      }
    }
    description
      "Access operation.";
  }

  typedef group-name-type {
    type string {
      length "1..max";
      pattern '[^\*].*';
    }
    description
      "Name of administrative group to which
       users can be assigned.";
  }

  typedef action-type {
    type enumeration {
      enum permit {
        description
          "Requested action is permitted.";
      }
      enum deny {
        description
          "Requested action is denied.";
      }
    }
    description
      "Action taken by the server when a particular
       rule matches.";
  }

  typedef node-instance-identifier {
    type yang:xpath1.0;
    description
      "Path expression used to represent a special
       data node, action, or notification instance-identifier
       string.

       A node-instance-identifier value is an
       unrestricted YANG instance-identifier expression.

       All the same rules as an instance-identifier apply,
       except that predicates for keys are optional.  If a key
       predicate is missing, then the node-instance-identifier
       represents all possible server instances for that key.
          This XML Path Language (XPath) expression is evaluated in the
          following context:

             o  The set of namespace declarations are those in scope on
                the leaf element where this type is used.

             o  The set of variable bindings contains one variable,
                'USER', which contains the name of the user of the
                current session.

             o  The function library is the core function library, but
                note that due to the syntax restrictions of an
                instance-identifier, no functions are allowed.

             o  The context node is the root node in the data tree.

          The accessible tree includes actions and notifications tied
          to data nodes.";
     }

     /*
      * Data definition statements
      */

     container nacm {
       nacm:default-deny-all;

       description
         "Parameters for NETCONF access control model.";

       leaf enable-nacm {
         type boolean;
         default "true";
         description
           "Enables or disables all NETCONF access control
            enforcement.  If 'true', then enforcement
            is enabled.  If 'false', then enforcement
            is disabled.";
       }
       leaf read-default {
         type action-type;
         default "permit";
         description
           "Controls whether read access is granted if
            no appropriate rule is found for a
            particular read request.";
       }

       leaf write-default {
         type action-type;
         default "deny";
         description
           "Controls whether create, update, or delete access
            is granted if no appropriate rule is found for a
            particular write request.";
       }

       leaf exec-default {
         type action-type;
         default "permit";
         description
           "Controls whether exec access is granted if no appropriate
            rule is found for a particular protocol operation request.";
       }

       leaf enable-external-groups {
         type boolean;
         default "true";
         description
           "Controls whether the server uses the groups reported by the
            NETCONF transport layer when it assigns the user to a set of
            NACM groups.  If this leaf has the value 'false', any group
            names reported by the transport layer are ignored by the
            server.";
       }

       leaf denied-operations {
         type yang:zero-based-counter32;
         config false;
         mandatory true;
         description
           "Number of times since the server last restarted that a
            protocol operation request was denied.";
       }
       leaf denied-data-writes {
         type yang:zero-based-counter32;
         config false;
         mandatory true;
         description
           "Number of times since the server last restarted that a
            protocol operation request to alter
            a configuration datastore was denied.";
       }

       leaf denied-notifications {
         type yang:zero-based-counter32;
         config false;
         mandatory true;
         description
           "Number of times since the server last restarted that
            a notification was dropped for a subscription because
            access to the event type was denied.";
       }

       container groups {
         description
           "NETCONF access control groups.";

         list group {
           key name;

           description
             "One NACM group entry.  This list will only contain
              configured entries, not any entries learned from
              any transport protocols.";

           leaf name {
             type group-name-type;
             description
               "Group name associated with this entry.";
           }

           leaf-list user-name {
             type user-name-type;
             description
               "Each entry identifies the username of
                a member of the group associated with
                this entry.";
           }
         }
       }
       list rule-list {
         key name;
         ordered-by user;
         description
           "An ordered collection of access control rules.";

         leaf name {
           type string {
             length "1..max";
           }
           description
             "Arbitrary name assigned to the rule-list.";
         }
         leaf-list group {
           type union {
             type matchall-string-type;
             type group-name-type;
           }
           description
             "List of administrative groups that will be
              assigned the associated access rights
              defined by the 'rule' list.

              The string '*' indicates that all groups apply to the
              entry.";
         }

         list rule {
           key name;
           ordered-by user;
           description
             "One access control rule.

              Rules are processed in user-defined order until a match is
              found.  A rule matches if 'module-name', 'rule-type', and
              'access-operations' match the request.  If a rule
              matches, the 'action' leaf determines whether or not
              access is granted.";

           leaf name {
             type string {
               length "1..max";
             }
             description
               "Arbitrary name assigned to the rule.";
           }
           leaf module-name {
             type union {
               type matchall-string-type;
               type string;
             }
             default "*";
             description
               "Name of the module associated with this rule.

                This leaf matches if it has the value '*' or if the
                object being accessed is defined in the module with the
                specified module name.";
           }
           choice rule-type {
             description
               "This choice matches if all leafs present in the rule
                match the request.  If no leafs are present, the
                choice matches all requests.";
             case protocol-operation {
               leaf rpc-name {
                 type union {
                   type matchall-string-type;
                   type string;
                 }
                 description
                   "This leaf matches if it has the value '*' or if
                    its value equals the requested protocol operation
                    name.";
               }
             }
             case notification {
               leaf notification-name {
                 type union {
                   type matchall-string-type;
                   type string;
                 }
                 description
                   "This leaf matches if it has the value '*' or if its
                    value equals the requested notification name.";
               }
             }
             case data-node {
               leaf path {
                 type node-instance-identifier;
                 mandatory true;
                 description
                   "Data node instance-identifier associated with the
                    data node, action, or notification controlled by
                    this rule.

                    Configuration data or state data
                    instance-identifiers start with a top-level
                    data node.  A complete instance-identifier is
                    required for this type of path value.

                    The special value '/' refers to all possible
                    datastore contents.";
               }
             }
           }

           leaf access-operations {
             type union {
               type matchall-string-type;
               type access-operations-type;
             }
             default "*";
             description
               "Access operations associated with this rule.

                This leaf matches if it has the value '*' or if the
                bit corresponding to the requested operation is set.";
           }

           leaf action {
             type action-type;
             mandatory true;
             description
               "The access control action associated with the
                rule.  If a rule has been determined to match a
                particular request, then this object is used
                to determine whether to permit or deny the
                request.";
           }
           leaf comment {
             type string;
             description
               "A textual description of the access rule.";
           }
         }
       }
     }
   }

   <CODE ENDS>

4. IANA Considerations ✨

Okay bestie, this part is all about the registries πŸ“‡. This document just reuses the existing URI for ietf-netconf-acm in the "IETF XML Registry" πŸ”—.

It also updates the module registration in the "YANG Module Names" registry so that it points to this RFC instead of RFC 6536 for ietf-netconf-acm 🫢. Following the format in [RFC6020], the entry looks like this:

        Name: ietf-netconf-acm
        Namespace: urn:ietf:params:xml:ns:yang:ietf-netconf-acm
        Prefix: nacm
        Reference: RFC 8341

5. Security Considerations πŸ”

Okay, this section is lowkey the most important part of the whole doc 😭. The YANG module here defines a schema for data that's meant to be reached through network management protocols like NETCONF [RFC6241] or RESTCONF [RFC8040]. For NETCONF, the bottom layer is the secure transport layer, and the mandatory-to-implement one is Secure Shell (SSH) [RFC6242]. For RESTCONF, the bottom layer is HTTPS, and the mandatory-to-implement secure transport is TLS [RFC5246] πŸ”’.

The NETCONF access control model [RFC8341] (aka this whole doc πŸ’…) gives you a way to limit particular NETCONF or RESTCONF users to a preset subset of the protocol operations and content that are available. It's giving bouncer at the door πŸšͺ✨.

Now the scary bit πŸ’€. There's a risk tied to a lack of access control enforcement for the RESTCONF OPTIONS and PATCH methods. The response to OPTIONS and PATCH can change depending on whether a resource exists at the URL's path. If it does, someone could trivially probe for whether values exist inside a tree πŸ™ˆ. So a server MUST NOT vary its responses based on whether the underlying resource exists, because that would reveal whether resource instances are present or absent. Servers should also avoid exposing any instance information before they've confirmed the client has the permissions needed to see it. In those cases, servers are expected to always return the "access-denied" error response 🚫.

There are also a bunch of data nodes in this YANG module that are writable, creatable, and deletable (basically config true, which is the default) πŸ“. They might be sensitive or vulnerable in some network environments, and writing to them (for example with edit-config) without proper protection can seriously mess with network operations. Here's the subtree to watch and why:

  • /nacm: The whole /nacm subtree is security-related, so check out the sections below for the details πŸ‘‘.

Last but not least, this section is here to flag the stuff an administrator should think about when configuring a NETCONF server with the NACM πŸ§šπŸ’œ.

5.1. NACM Configuration and Monitoring Considerations πŸ”

okay so configuring the access control system is seriously sensitive stuff, bestie πŸ” A server is allowed to lock down some parts of it from user config, like the global security level or the groups that get access to system resources. Protecting the gatekeeper is literally the whole job πŸ’…

By default, NACM enforcement is turned on ✨ By default, "read" access to all datastore contents is on too (unless nacm:default-deny-all is set for the data definition), and "exec" access is on for safe protocol operations 🌸 An administrator needs to make sure NACM is enabled and decide whether those default access settings are actually right for their setup. Make sure these data nodes are properly configured:

  • /nacm/enable-nacm (default "true")
  • /nacm/read-default (default "permit")
  • /nacm/write-default (default "deny")
  • /nacm/exec-default (default "permit")

An administrator needs to restrict write access to all configurable objects in this data model πŸŽ€

If write access is allowed for configuring access control rules, then care needs to be taken so the access control enforcement doesn't get disrupted πŸ™ˆ For example, if the NACM access control rules are edited directly within the running configuration datastore (that is, the :writable-running capability is supported and used), then care needs to be taken not to allow unintended access while those edits are happening. Yikes, the vibes are fragile 😭

An administrator needs to make sure the translation from a transport- or implementation-dependent user identity to a NACM username is unique and correct. This requirement is spelled out in detail in Section 2.2 of [RFC6241] πŸ¦‹

An administrator also needs to know that the YANG data structures representing access control rules (/nacm/rule-list and /nacm/rule-list/rule) are ordered by the client. The server evaluates the access control rules according to their relative conceptual order within the running configuration datastore, so the order literally matters ✨

Quick note: the /nacm/groups data structure holds the administrative group names used by the server. These group names may be configured locally, and/or provided through an external protocol such as RADIUS [RFC2865] [RFC5607] πŸ“

An administrator needs to understand the security properties of any external protocol the transport layer uses to figure out group names πŸ‘€ For example, if that protocol doesn't protect against man-in-the-middle attacks, an attacker might be able to inject group names that are configured in NACM, so a user ends up with more permissions than they should have. Not okay! In that situation, the administrator may want to turn off the use of those group names by setting /nacm/enable-external-groups to "false" πŸ›‘οΈ

Some of the readable data nodes in this YANG module might be considered sensitive or vulnerable in certain network environments, so it's important to control read access to them (for example, via get, get-config, or notification) 🫢 These are the subtrees and data nodes, along with why they're sensitive or vulnerable:

  • /nacm/enable-nacm
  • /nacm/read-default
  • /nacm/write-default
  • /nacm/exec-default
  • /nacm/enable-external-groups
  • /nacm/groups
  • /nacm/rule-list

An administrator needs to restrict read access to all of the objects listed above, because they reveal access control configuration that could be considered sensitive πŸ”₯


5.2. General Configuration Issues 🧩

There's a risk that invoking non-standard protocol operations will have undocumented side effects πŸ’€ An administrator needs to build access control rules so the configuration datastore stays protected from those side effects.

A session can have some write access (for example, being allowed to invoke <edit-config>) but no access to a particular datastore subtree that holds sensitive data, and still figure out whether that data is present or not πŸ•΅οΈβ€β™€οΈ It works by repeatedly sending some kind of edit request (create, update, or delete) and possibly getting "access-denied" errors back. These "fishing" attacks can reveal whether specific sensitive data exists, even without the "error-path" field being present within the <rpc-error> response. Sneaky!

The set of NETCONF capabilities on the server might change over time. If that happens, there's a risk that new protocol operations, notifications, and/or datastore content have been added to the device. In that case, an administrator needs to be sure the access control rules are correct for the new content. Mechanisms for detecting NETCONF capability changes on a specific device are outside the scope of this document 🌈

It's possible that the data model definition itself (for example, a YANG when-stmt) will help an unauthorized session work out whether sensitive data nodes exist, or even what their values are, by checking the presence and values of different data nodes πŸ‘οΈ

It's also possible that the data model definition itself (for example, a YANG when-stmt or choice-stmt) will let a session implicitly create or delete nodes it doesn't have write access to, as an implicit side effect of processing an allowed <edit-config> operation. Sneaky side effects, periodt πŸ’…

There's a risk that non-standard protocol operations, or even the standard <get> protocol operation, may return data that "aliases" or "copies" sensitive data from a different data object. Multiple data model definitions might expose, or even configure, the same underlying system instrumentation πŸͺž

A data model may contain external keys (for example, YANG leafref), which expose values from a different data structure. An administrator needs to be aware of sensitive data models that contain leafref nodes. That means finding all the leafref objects that "point" at the sensitive data (that is, the path-stmt values) that implicitly or explicitly include the sensitive data node πŸ”

It's beyond the scope of this document to define access control enforcement procedures for the underlying device instrumentation that may exist to support NETCONF server operation. An administrator can identify each protocol operation the server provides and decide whether it needs any access control applied πŸ“‹

This document incorporates the optional use of a recovery session mechanism, which can be used to bypass access control enforcement in emergencies, such as NACM configuration errors that disable all access to the server 🚨 How that recovery session mechanism is configured and identified is implementation specific and outside the scope of this document. An administrator needs to know about any recovery session mechanisms available on the device and make sure they're used appropriately.

A session can disrupt configuration management even without any write access to the configuration, by locking the datastore πŸ”’ This might be done to keep all or part of the configuration stable while it's being retrieved, or it might be a "denial-of-service" attack. The server has no way of knowing the difference! An administrator may want to restrict "exec" access to these protocol operations:

  • <lock>
  • <unlock>
  • <partial-lock>
  • <partial-unlock>

5.3. Data Model Design Considerations πŸŽ€

Designers need to clearly identify any sensitive data, notifications, or protocol operations defined within a YANG module ✨ For those definitions, a nacm:default-deny-write or nacm:default-deny-all statement ought to be present, along with a clear description of the security risks.

Protocol operations need to be properly documented by the data model designer, so it's clear to administrators which data nodes (if any) the operation affects and what information (if any) is returned in the <rpc-reply> message πŸ“–

Data models ought to be designed so that different access levels for input parameters to protocol operations aren't required. Generic protocol operations should be avoided. If different access levels are needed, separate protocol operations should be defined instead 🌸


6. References πŸ“š

6.1. Normative References πŸ¦‹

6.2. Informative References ✨

Okay, last stretch bestie! These are the informative references, the "nice to know" reads that back up the doc without being required reading. πŸ“š


Appendix A. Usage Examples 🌸

Bestie, this appendix is my favourite bit. These XML [W3C.REC-xml-20081126] snippets are examples only! They just show how NACM can be set up to handle some access control jobs. Think of them as outfit inspo, not a dress code. πŸ’…

A.1. <groups> Example πŸ‘―

There needs to be at least one <group> entry, otherwise none of the access control rules can actually do anything. πŸ₯Ί

The XML below shows arbitrary groups. It isn't meant to match any real use case, so don't read too much into the names. 🧚

<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <groups>
    <group>
      <name>admin</name>
      <user-name>admin</user-name>
      <user-name>andy</user-name>
    </group>

    <group>
      <name>limited</name>
      <user-name>wilma</user-name>
      <user-name>bam-bam</user-name>
    </group>

    <group>
      <name>guest</name>
      <user-name>guest</user-name>
      <user-name>guest@example.com</user-name>
    </group>
  </groups>
</nacm>

So this example has three groups:

  • admin: the "admin" group holds two users, "admin" and "andy". πŸ‘‘
  • limited: the "limited" group holds two users, "wilma" and "bam-bam". 🌈
  • guest: the "guest" group holds two users, "guest" and "guest@example.com". πŸ“

A.2. Module Rule Example πŸ“¦

Module rules control access to all the content defined in one specific module. A module rule has the "module-name" leaf set, but none of the nodes from the "rule-type" choice are set. Iconic, right? πŸ’–

<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <rule-list>
    <name>guest-acl</name>
    <group>guest</group>

    <rule>
      <name>deny-ncm</name>
      <module-name>ietf-netconf-monitoring</module-name>
      <access-operations>*</access-operations>
      <action>deny</action>
      <comment>
          Do not allow guests any access to the NETCONF
          monitoring information.
      </comment>
    </rule>
  </rule-list>

  <rule-list>
    <name>limited-acl</name>
    <group>limited</group>

    <rule>
      <name>permit-ncm</name>
      <module-name>ietf-netconf-monitoring</module-name>
      <access-operations>read</access-operations>
      <action>permit</action>
      <comment>
          Allow read access to the NETCONF
          monitoring information.
      </comment>
    </rule>
    <rule>
      <name>permit-exec</name>
      <module-name>*</module-name>
      <access-operations>exec</access-operations>
      <action>permit</action>
      <comment>
          Allow invocation of the
          supported server operations.
      </comment>
    </rule>
  </rule-list>
  <rule-list>
    <name>admin-acl</name>
    <group>admin</group>

    <rule>
      <name>permit-all</name>
      <module-name>*</module-name>
      <access-operations>*</access-operations>
      <action>permit</action>
      <comment>
          Allow the 'admin' group complete access to all
          operations and data.
      </comment>
    </rule>
  </rule-list>
</nacm>

This example shows four module rules:

  • deny-ncm: blocks the "guest" group from reading any monitoring info in the "ietf-netconf-monitoring" YANG module. πŸ™…β€β™€οΈ
  • permit-ncm: lets the "limited" group read the "ietf-netconf-monitoring" YANG module. πŸ“–
  • permit-exec: lets the "limited" group invoke any protocol operation the server supports. ⚑
  • permit-all: gives the "admin" group complete access to all content on the server. Because of this module rule, no later rule will ever match for the "admin" group. Main character energy! πŸ‘‘

A.3. Protocol Operation Rule Example πŸ› οΈ

Protocol operation rules control access to one specific protocol operation. 🧠

<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <rule-list>
    <name>guest-limited-acl</name>
    <group>limited</group>
    <group>guest</group>

    <rule>
      <name>deny-kill-session</name>
      <module-name>ietf-netconf</module-name>
      <rpc-name>kill-session</rpc-name>
      <access-operations>exec</access-operations>
      <action>deny</action>
      <comment>
        Do not allow the 'limited' group or the 'guest' group
        to kill another session.
      </comment>
    </rule>
    <rule>
      <name>deny-delete-config</name>
      <module-name>ietf-netconf</module-name>
      <rpc-name>delete-config</rpc-name>
      <access-operations>exec</access-operations>
      <action>deny</action>
      <comment>
        Do not allow the 'limited' group or the 'guest' group
        to delete any configurations.
      </comment>
    </rule>
  </rule-list>
  <rule-list>
    <name>limited-acl</name>
    <group>limited</group>

    <rule>
      <name>permit-edit-config</name>
      <module-name>ietf-netconf</module-name>
      <rpc-name>edit-config</rpc-name>
      <access-operations>exec</access-operations>
      <action>permit</action>
      <comment>
        Allow the 'limited' group to edit the configuration.
      </comment>
    </rule>
  </rule-list>
</nacm>

This example shows three protocol operation rules:

  • deny-kill-session: stops the "limited" group or the "guest" group from invoking the NETCONF <kill-session> protocol operation. 🚫
  • deny-delete-config: stops the "limited" group or the "guest" group from invoking the NETCONF <delete-config> protocol operation. πŸ—‘οΈ
  • permit-edit-config: lets the "limited" group invoke the NETCONF <edit-config> protocol operation. Heads up, this rule won't have any real effect unless the "exec-default" leaf is set to "deny". πŸ‘€

A.4. Data Node Rule Example πŸ—‚οΈ

Data node rules control access to specific config and non-config data nodes inside the NETCONF content the server provides. πŸ’Ž

<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <rule-list>
    <name>guest-acl</name>
    <group>guest</group>

    <rule>
      <name>deny-nacm</name>
      <path xmlns:n="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
        /n:nacm
      </path>
      <access-operations>*</access-operations>
      <action>deny</action>
      <comment>
        Deny the 'guest' group any access to the /nacm data.
      </comment>
    </rule>
  </rule-list>

  <rule-list>
    <name>limited-acl</name>
    <group>limited</group>

    <rule>
      <name>permit-acme-config</name>
      <path xmlns:acme="http://example.com/ns/netconf">
        /acme:acme-netconf/acme:config-parameters
      </path>
      <access-operations>
        read create update delete
      </access-operations>
      <action>permit</action>
      <comment>
        Allow the 'limited' group complete access to the acme
        NETCONF configuration parameters.  Showing long form
        of 'access-operations' instead of shorthand.
      </comment>
    </rule>
  </rule-list>
  <rule-list>
    <name>guest-limited-acl</name>
    <group>guest</group>
    <group>limited</group>

    <rule>
      <name>permit-dummy-interface</name>
      <path xmlns:acme="http://example.com/ns/itf">
        /acme:interfaces/acme:interface[acme:name='dummy']
      </path>
      <access-operations>read update</access-operations>
      <action>permit</action>
      <comment>
        Allow the 'limited' and 'guest' groups read
        and update access to the dummy interface.
      </comment>
    </rule>
  </rule-list>

  <rule-list>
    <name>admin-acl</name>
    <group>admin</group>
    <rule>
      <name>permit-interface</name>
      <path xmlns:acme="http://example.com/ns/itf">
        /acme:interfaces/acme:interface
      </path>
      <access-operations>*</access-operations>
      <action>permit</action>
      <comment>
        Allow the 'admin' group full access to all acme interfaces.
      </comment>
    </rule>
  </rule-list>
</nacm>

This example shows four data node rules:

  • deny-nacm: denies the "guest" group any access to the /nacm subtree. πŸ”’
  • permit-acme-config: gives the "limited" group read-write access to the acme <config-parameters>. ✏️
  • permit-dummy-interface: gives the "limited" and "guest" groups read-update access to the acme <interface> entry named "dummy". That entry can't be created or deleted by these groups. It can only be altered. 🧸
  • permit-interface: gives the "admin" group read-write access to all acme <interface> entries. 🌟

A.5. Notification Rule Example πŸ””

Notification rules control access to one specific notification event type. πŸ“£

<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <rule-list>
    <name>sys-acl</name>
    <group>limited</group>
    <group>guest</group>

    <rule>
      <name>deny-config-change</name>
      <module-name>acme-system</module-name>
      <notification-name>sys-config-change</notification-name>
      <access-operations>read</access-operations>
      <action>deny</action>
      <comment>
        Do not allow the 'guest' group or the 'limited' group
        to receive config change events.
      </comment>
    </rule>
  </rule-list>
</nacm>

This example shows one notification rule:

  • deny-config-change: stops the "limited" group or the "guest" group from receiving the acme <sys-config-change> event type. 🚷

Authors' Addresses πŸ–‹οΈ

Andy Bierman
YumaWorks
685 Cochran St.
Suite #160
Simi Valley, CA  93065
United States of America

Email: andy@yumaworks.com


Martin Bjorklund
Tail-f Systems

Email: mbj@tail-f.com

And that's the whole doc, bestie! πŸŒˆπŸ’– We made it through every single section. 🫢

πŸ“¦ where this page comes from