RFC 8650
Dynamic Subscription to YANG Events and Datastores over RESTCONF
Dynamic Subscription to YANG Events and Datastores over RESTCONF ๐ฆ
okay so this is RFC 8650 ๐ It's a Standards Track document from the IETF, dated November 2019, with ISSN 2070-1721. Five people wrote it: E. Voit, R. Rahman, E. Nilsen-Nygaard (Cisco Systems), A. Clemm (Futurewei), and A. Bierman (YumaWorks). The header doesn't list anything it obsoletes or updates, so it's standing on its own, and it's giving main character energy ๐ซถ
Abstract โจ
bestie, the whole point is a RESTCONF binding for the dynamic subscription capability of both subscribed notifications and YANG-Push. So it's the RESTCONF way to set up those dynamic subscriptions ๐
Status of This Memo ๐
This is an Internet Standards Track document. โ
It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841 ๐ธ
For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc8650.
Copyright Notice ยฉ๏ธ
Copyright (c) 2019 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) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Simplified BSD License.
Table of Contents ๐บ๏ธ
1. Introduction
2. Terminology
3. Dynamic Subscriptions
3.1. Transport Connectivity
3.2. Discovery
3.3. RESTCONF RPCs and HTTP Status Codes
3.4. Call Flow for Server-Sent Events
4. QoS Treatment
5. Notification Messages
6. YANG Tree
7. YANG Module
8. IANA Considerations
9. Security Considerations
10. References
10.1. Normative References
10.2. Informative References
Appendix A. Examples
A.1. Dynamic Subscriptions
A.1.1. Establishing Dynamic Subscriptions
A.1.2. Modifying Dynamic Subscriptions
A.1.3. Deleting Dynamic Subscriptions
A.2. Subscription State Notifications
A.2.1. "subscription-modified"
A.2.2. "subscription-completed", "subscription-resumed", and
"replay-completed"
A.2.3. "subscription-terminated" and "subscription-suspended"
A.3. Filter Example
Acknowledgments
Authors' Addresses
1. Introduction ๐
So the event subscription and YANG-Push mechanisms are defined in [RFC8639]. The upgrades that let you subscribe to YANG datastores and do YANG-Push are in [RFC8641]. This document is the transport spec: it covers dynamic subscriptions over RESTCONF [RFC8040]. The requirements for all of this live in [RFC7923] ๐
Now, the notifications that carry the resulting information push get streamed using the mechanism in Section 6.3 of [RFC8040]. It's a whole chain of slay ๐
2. 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. ๐ฅ So only the all-caps versions carry that meaning, bestie.
The following terms use the definitions from [RFC8639]: dynamic subscription, event stream, notification message, publisher, receiver, subscriber, and subscription. ๐ซถ
Other terms reused include datastore, which is defined in [RFC8342], and HTTP/2 stream, which maps to the definition of "stream" within [RFC7540], Section 2 ๐ฆ
3. Dynamic Subscriptions ๐ง
This section gets into the specifics of how to set up and keep up dynamic subscriptions over RESTCONF [RFC8040]. Subscribing to event streams happens through RPCs defined in [RFC8639], Section 2.4. Those RPCs are sent as RESTCONF POSTs. YANG datastore subscription comes from augmentations to [RFC8639], as described in [RFC8641], Section 4.4 ๐
Here's the tea ๐ต As described in Section 6.3 of [RFC8040], you need to do a GET on a specific URI on the publisher. Subscribers can't predetermine that URI, because it only exists after the "establish-subscription" RPC has been accepted. So the POST for "establish-subscription" takes the place of the GET request for the "location" leaf that [RFC8040] uses to get the URI. The subscription URI gets figured out and sent back in the response to "establish-subscription", and then a GET to that URI starts the flow of notification messages to the subscriber. As specified in Section 2.4.1 of [RFC8639], a subscription doesn't move to the active state until that GET is received ๐ญ
3.1. Transport Connectivity ๐
When a dynamic subscription comes in and there isn't already a RESTCONF session, a new RESTCONF session gets started from the subscriber ๐
As stated in Section 2.1 of [RFC8040], a subscriber MUST establish the HTTP session over TLS [RFC8446] to keep the content secure in transit ๐
Plain HTTP sessions don't have a built-in way to spot quickly that the path to the publisher is gone ๐ So if you need to notice that fast, a subscriber SHOULD use a TLS heartbeat [RFC6520], just from subscriber to publisher, to keep track of HTTP session continuity.
Loss of the heartbeat MUST result in the teardown of any subscription-related TCP sessions between those endpoints. Then the subscriber can try to re-establish the dynamic subscription using the procedure in Section 3.4 ๐
3.2. Discovery ๐
Subscribers can find out which event streams a RESTCONF server supports by querying the "streams" container of ietf-subscribed-notifications.yang in [RFC8639]. Support for the "streams" container of ietf-restconf-monitoring.yang in [RFC8040] is not required. But if the RESTCONF binding from this document is used to convey the "streams" container from ietf-restconf-monitoring.yang (meaning that feature is supported), any event streams in there are also expected to show up in the "streams" container of ietf-restconf-monitoring.yang โจ
And subscribers can find out which datastores a RESTCONF server supports by following Section 2 of [RFC8527] ๐
3.3. RESTCONF RPCs and HTTP Status Codes
okay so this is where the HTTP status codes come in ๐ โจ bestie, the way that RESTCONF RPCs talk back to you is through standard HTTP response codes, the ones from Section 6 of [RFC7231] ๐ฆ. Totally iconic. A publisher answers any RPC that succeeds with an HTTP status code of 200, no cap, that's the vibe for "all good" ๐ธ
Now, if a publisher can't serve an RPC request for one of the reasons listed in Section 2.4.6 of [RFC8639] or Appendix A of [RFC8641] ๐, it shows up as an error code (you'll see the tables below) and that gets carried in the HTTP response ๐ซถ
When an HTTP error code comes back, the RPC reply MUST include an <rpc-error> element per Section 7.1 of [RFC8040] ๐ with these parameter values:
- an "error-type" node of "application" ๐
- an "error-tag" node whose value is a string matching an identity linked to the error ๐ฅ This tag comes from one of two places: the error identities in Section 2.4.6 of [RFC8639] for general subscription errors (Table 1), or the ones in Appendix A.1 of [RFC8641] for subscription errors specific to YANG datastores (Table 2) ๐ง
- an "error-app-tag" node whose value is a string matching an identity linked to the error, as defined in Section 2.4.6 of [RFC8639] for general subscriptions or Appendix A.1 of [RFC8641] for datastore-specific errors ๐ The tag you use depends on which RPC threw the error, and you can find the viable errors for each RPC in Table 3 ๐
+------------------------+-------------------------+-----------+
| Error identity | Uses "error-tag" | HTTP code |
+========================+=========================+===========+
| dscp-unavailable | invalid-value | 400 |
+------------------------+-------------------------+-----------+
| encoding-unsupported | invalid-value | 400 |
+------------------------+-------------------------+-----------+
| filter-unsupported | invalid-value | 400 |
+------------------------+-------------------------+-----------+
| insufficient-resources | resource-denied | 409 |
+------------------------+-------------------------+-----------+
| no-such-subscription | invalid-value | 404 |
+------------------------+-------------------------+-----------+
| replay-unsupported | operation-not-supported | 501 |
+------------------------+-------------------------+-----------+
Table 1: General Subscription Error Identities and
Associated "error-tag" Use
+-----------------------------+-------------------------+-----------+
| Error identity | Uses "error-tag" | HTTP |
| | | code |
+=============================+=========================+===========+
| cant-include | operation-not-supported | 501 |
+-----------------------------+-------------------------+-----------+
| datastore-not-subscribable | invalid-value | 400 |
+-----------------------------+-------------------------+-----------+
| no-such-subscription-resync | invalid-value | 404 |
+-----------------------------+-------------------------+-----------+
| on-change-unsupported | operation-not-supported | 501 |
+-----------------------------+-------------------------+-----------+
| on-change-sync-unsupported | operation-not-supported | 501 |
+-----------------------------+-------------------------+-----------+
| period-unsupported | invalid-value | 400 |
+-----------------------------+-------------------------+-----------+
| update-too-big | too-big | 400 |
+-----------------------------+-------------------------+-----------+
| sync-too-big | too-big | 400 |
+-----------------------------+-------------------------+-----------+
| unchanging-selection | operation-failed | 500 |
+-----------------------------+-------------------------+-----------+
Table 2: Datastore-Specific Error Identities and Associated
"error-tag" Use
+------------------------+--------------------------------+
| RPC | Select an identity with a base |
+========================+================================+
| establish-subscription | establish-subscription-error |
+------------------------+--------------------------------+
| modify-subscription | modify-subscription-error |
+------------------------+--------------------------------+
| delete-subscription | delete-subscription-error |
+------------------------+--------------------------------+
| kill-subscription | delete-subscription-error |
+------------------------+--------------------------------+
| resync-subscription | resync-subscription-error |
+------------------------+--------------------------------+
Table 3: RPC Errors and Associated Error Identities
Each error identity gets inserted as the "error-app-tag" using JSON encoding in the form <modulename>:<identityname> ๐ฆ A valid example would be "ietf-subscribed-notifications:no-such-subscription" โจ
For error responses to an "establish-subscription" or "modify-subscription" request, you're allowed to include an "error-info" node ๐ It may contain hints for parameter settings that could lead to successful RPC requests in the future ๐ฎ Tables 4 and 5 show the yang-data structures that can come back.
+--------------+---------------------------------------------+
| Target: | Return hints in yang-data structure |
+==============+=============================================+
| event stream | establish-subscription-stream-error-info |
+--------------+---------------------------------------------+
| datastore | establish-subscription-datastore-error-info |
+--------------+---------------------------------------------+
Table 4: Optional "error-info" Node Hints for an
"establish-subscription" Request
+--------------+------------------------------------------+
| Target: | Returns hints in yang-data structure |
+==============+==========================================+
| event stream | modify-subscription-stream-error-info |
+--------------+------------------------------------------+
| datastore | modify-subscription-datastore-error-info |
+--------------+------------------------------------------+
Table 5: Optional "error-info" Node Hints for an
"modify-subscription" Request
The yang-data inside "error-info" SHOULD NOT include the optional leaf "reason" ๐ Why? Because it would just repeat what's already in the "error-app-tag" ๐
If an <rpc-error> comes back from a "delete-subscription", "kill-subscription", or "resync-subscription" request, you don't need to include any "error-info" ๐ธ The "subscription-id" is the only RPC input parameter there, so there are no hints about RPC input parameters to give โจ
Also, "error-path" [RFC8040] doesn't need to be included with the <rpc-error> element ๐ Subscription errors are generally tied to the choice of RPC input parameters, so it's not needed ๐ซถ
3.4. Call Flow for Server-Sent Events ๐
Okay so, the call flow for Server-Sent Events (SSE) is all laid out in Figure 1 ๐ฆ. The two logical connections, (a) and (b), can each be a TCP connection or an HTTP/2 stream. If you're on HTTP/2, you can fit multiple streams into one TCP connection. RPC requests defined in [RFC8639] or [RFC8641] go over the connection marked (a). A successful "establish-subscription" hands back an RPC response with a subscription identifier that uniquely identifies the subscription, plus a URI that uniquely pins down where that subscription lives on the publisher (b). That URI comes from the "uri" leaf in the data model in Section 7.
Next up, an HTTP GET goes out on a separate logical connection (b) to that URI. This is the signal telling the publisher to start streaming notification messages, which come back as SSE [W3C-20150203] in response to the GET. Only one GET can be open on a subscription URI at a time. Any GET that shows up while another GET is already active on the same URI MUST be rejected with HTTP error code 409 ๐ โโ๏ธ.
As described in Section 6.4 of [RFC8040], RESTCONF servers SHOULD NOT send the "event" or "id" fields in the SSE event notifications ๐.
+--------------+ +--------------+
| Subscriber | | Publisher |
| | | |
| Logical | | Logical |
| Connection | | Connection |
| (a) (b) | | (a) (b) |
+--------------+ +--------------+
| RESTCONF POST (RPC:establish-subscription) |
|--------------------------------------------->|
| HTTP 200 OK (ID,URI)|
|<---------------------------------------------|
| |HTTP GET (URI) |
| |--------------------------------------------->|
| | HTTP 200 OK|
| |<---------------------------------------------|
| | SSE (notif-message)|
| |<---------------------------------------------|
| RESTCONF POST (RPC:modify-subscription) | |
|--------------------------------------------->| |
| | HTTP 200 OK| |
|<---------------------------------------------| |
| | SSE (subscription-modified)|
| |<------------------------------------------(c)|
| | SSE (notif-message)|
| |<---------------------------------------------|
| RESTCONF POST (RPC:delete-subscription) | |
|--------------------------------------------->| |
| | HTTP 200 OK| |
|<---------------------------------------------| |
| | | |
| | | |
(a) (b) (a) (b)
Figure 1: Dynamic Subscriptions with Server-Sent Events
Here are the extra requirements for dynamic subscriptions over SSE ๐ธ:
- A publisher MUST return all subscription state notifications in a separate SSE message, sent on the subscription that the state change is about.
- Subscription RPCs MUST NOT use the connection that's currently delivering notification messages for that subscription.
- Along with the RPC response for a "modify-subscription" RPC coming back over (a), a "subscription-modified" state change notification MUST be sent within (b). This lets the receiver see exactly when, within the stream of events, the new terms of the subscription have kicked in for the notification messages. Check arrow (c) ๐.
- On top of any required access permissions (for example, Network Configuration Access Control Model (NACM)), the RPCs "modify-subscription", "resync-subscription", and "delete-subscription" SHOULD only be allowed for the same RESTCONF username [RFC8040] that invoked "establish-subscription". This mostly keeps users' privacy safe, though admins might get exceptions so they can change or delete other users' subscriptions when they really need to ๐.
- Any RESTCONF username with the required administrative permissions can invoke the "kill-subscription" RPC ๐.
A publisher MUST terminate a subscription in these cases:
- Receipt of a "delete-subscription" or a "kill-subscription" RPC for that subscription
- Loss of TLS heartbeat
A publisher MAY terminate a subscription at any time, as stated in Section 1.3 of [RFC8639] โจ.
4. QoS Treatment ๐
QoS treatment for event streams is covered in Section 2.3 of [RFC8639]. On top of that, if HTTP/2 is used, the publisher MUST:
- Take the "weighting" leaf node in [RFC8639] and copy it into the HTTP/2 stream weight, Section 5.3 of [RFC7540], and
- Take any existing subscription "dependency", as specified by the "dependency" leaf node in [RFC8639], and use the HTTP/2 stream for the parent subscription as the HTTP/2 stream dependency (as described in Section 5.3.1 of [RFC7540]) of the dependent subscription.
- Set the exclusive flag (Section 5.3.1 of [RFC7540]) to 0.
For dynamic subscriptions with the same Differentiated Services Code Point (DSCP) value going to a specific publisher, it is recommended that the subscriber sends all URI GET requests on a common HTTP/2 session (if HTTP/2 is used). The flip side is that a subscriber cannot use a common HTTP/2 session for subscriptions with different DSCP values ๐.
5. Notification Messages ๐ซถ
Notification messages sent over RESTCONF will be encoded according to [RFC8040], Section 6.4 ๐.
6. YANG Tree ๐ณ
The YANG module defined in Section 7 has one leaf that augments three nodes of [RFC8639] ๐ง.
module: ietf-restconf-subscribed-notifications
augment /sn:establish-subscription/sn:output:
+--ro uri? inet:uri
augment /sn:subscriptions/sn:subscription:
+--ro uri? inet:uri
augment /sn:subscription-modified:
+--ro uri? inet:uri
7. YANG Module ๐
This module references [RFC8639] ๐.
<CODE BEGINS>
file "ietf-restconf-subscribed-notifications@2019-11-17.yang"
module ietf-restconf-subscribed-notifications {
yang-version 1.1;
namespace "urn:ietf:params:xml:ns:yang:"
+ "ietf-restconf-subscribed-notifications";
prefix rsn;
import ietf-subscribed-notifications {
prefix sn;
}
import ietf-inet-types {
prefix inet;
}
organization
"IETF NETCONF (Network Configuration) Working Group";
contact
"WG Web: <https://datatracker.ietf.org/wg/netconf/>
WG List: <mailto:netconf@ietf.org>
Editor: Eric Voit
<mailto:evoit@cisco.com>
Editor: Alexander Clemm
<mailto:ludwig@clemm.org>
Editor: Reshad Rahman
<mailto:rrahman@cisco.com>";
description
"Defines RESTCONF as a supported transport for subscribed
event notifications.
Copyright (c) 2019 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 8650; see the
RFC itself for full legal notices.";
revision 2019-11-17 {
description
"Initial version";
reference
"RFC 8650: Dynamic Subscription to YANG Events and Datastores
over RESTCONF";
}
grouping uri {
description
"Provides a reusable description of a URI.";
leaf uri {
type inet:uri;
config false;
description
"Location of a subscription-specific URI on the publisher.";
}
}
augment "/sn:establish-subscription/sn:output" {
description
"This augmentation allows RESTCONF-specific parameters for a
response to a publisher's subscription request.";
uses uri;
}
augment "/sn:subscriptions/sn:subscription" {
description
"This augmentation allows RESTCONF-specific parameters to be
exposed for a subscription.";
uses uri;
}
augment "/sn:subscription-modified" {
description
"This augmentation allows RESTCONF-specific parameters to be
included as part of the notification that a subscription has
been modified.";
uses uri;
}
}
<CODE ENDS>
8. IANA Considerations ๐
This document registers the following namespace URI in the "ns" subregistry of the "IETF XML Registry" [RFC3688] ๐๏ธ:
- URI:
urn:ietf:params:xml:ns:yang:ietf-restconf-subscribed-notifications - Registrant Contact: The IESG.
- XML: N/A; the requested URI is an XML namespace.
This document also registers the following YANG module in the "YANG Module Names" registry [RFC6020] ๐:
- Name:
ietf-restconf-subscribed-notifications - Namespace:
urn:ietf:params:xml:ns:yang:ietf-restconf-subscribed-notifications - Prefix:
rsn - Reference: RFC 8650
9. Security Considerations ๐
okay bestie, security is where we get serious ๐ค this YANG module is a schema for data that gets accessed over network management transports like NETCONF [RFC6241] or RESTCONF [RFC8040]. The lowest NETCONF layer is the secure transport layer, and the mandatory-to-implement secure transport there is Secure Shell (SSH) [RFC6242]. The lowest RESTCONF layer is HTTPS, and the mandatory-to-implement secure transport is TLS [RFC8446]. so yeah, security is built in from the ground up ๐
The Network Configuration Access Control Model (NACM) [RFC8341] is the bouncer ๐ช It lets you restrict particular NETCONF or RESTCONF users to a preconfigured subset of all the available NETCONF or RESTCONF protocol operations and content. main character energy for access control ๐
The one new data node introduced in this YANG module might count as sensitive or vulnerable in some network environments, so reading it needs guarding ๐ซฃ It is thus important to control read access (e.g., via get, get-config, or notification) to this data node. Here are the subtrees and data nodes, plus how sensitive or vulnerable they are:
Container: /subscriptions
uri: this leaf shows where subscribed resources might be located on a publisher. Access control must be set so that only someone with proper access permissions gets to see it. That means the same RESTCONF [RFC8040] user credentials that invoked the correspondingestablish-subscriptionare the only ones who can access this resource ๐
The subscription URI is implementation specific, and it's encrypted via the use of TLS ๐ So even if an attacker manages to guess the subscription URI, a RESTCONF username [RFC8040] with the required administrative permissions must be used to access or modify that subscription. Guessing alone won't get them in. It is recommended that the subscription URI values not be easily predictable, so don't make them obvious ๐
The access permission considerations for the RPCs modify-subscription, resync-subscription, delete-subscription, and kill-subscription are described in Section 3.4.
โ ๏ธ Buggy or compromised subscribers can be a real problem. If a buggy or compromised RESTCONF subscriber sends a bunch of establish-subscription requests, those subscriptions pile up and can eat through system resources ๐ In that situation, the publisher MAY also suspend or terminate a subset of the active subscriptions from that RESTCONF subscriber. The goal is to reclaim resources and keep things running smoothly for everyone else ๐งน
10. References ๐
10.1. Normative References
These are the must-read ones ๐ค
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.
- [RFC3688] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, <https://www.rfc-editor.org/info/rfc3688>.
- [RFC6020] Bjorklund, M., Ed., "YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)", RFC 6020, DOI 10.17487/RFC6020, October 2010, <https://www.rfc-editor.org/info/rfc6020>.
- [RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., "Network Configuration Protocol (NETCONF)", RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.
- [RFC6242] Wasserman, M., "Using the NETCONF Protocol over Secure Shell (SSH)", RFC 6242, DOI 10.17487/RFC6242, June 2011, <https://www.rfc-editor.org/info/rfc6242>.
- [RFC6520] Seggelmann, R., Tuexen, M., and M. Williams, "Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension", RFC 6520, DOI 10.17487/RFC6520, February 2012, <https://www.rfc-editor.org/info/rfc6520>.
- [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext Transfer Protocol Version 2 (HTTP/2)", RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.
- [RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, "RESTCONF Protocol", RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.
- [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.
- [RFC8341] Bierman, A. and M. Bjorklund, "Network Configuration Access Control Model", STD 91, RFC 8341, DOI 10.17487/RFC8341, March 2018, <https://www.rfc-editor.org/info/rfc8341>.
- [RFC8342] Bjorklund, M., Schoenwaelder, J., Shafer, P., Watsen, K., and R. Wilton, "Network Management Datastore Architecture (NMDA)", RFC 8342, DOI 10.17487/RFC8342, March 2018, <https://www.rfc-editor.org/info/rfc8342>.
- [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.
- [RFC8639] Voit, E., Clemm, A., Gonzalez Prieto, A., Nilsen-Nygaard, E., and A. Tripathy, "Subscription to YANG Notifications", RFC 8639, DOI 10.17487/RFC8639, September 2019, <https://www.rfc-editor.org/info/rfc8639>.
- [RFC8641] Clemm, A. and E. Voit, "Subscription to YANG Notifications for Datastore Updates", RFC 8641, DOI 10.17487/RFC8641, September 2019, <https://www.rfc-editor.org/info/rfc8641>.
- [W3C-20150203] Hickson, I., "Server-Sent Events", W3C Recommendation, 3 February 2015, <https://www.w3.org/TR/2015/REC-eventsource-20150203/>. Latest version available at <https://www.w3.org/TR/eventsource/>.
10.2. Informative References
These ones are for extra context ๐ธ
- [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014, <https://www.rfc-editor.org/info/rfc7231>.
- [RFC7923] Voit, E., Clemm, A., and A. Gonzalez Prieto, "Requirements for Subscription to YANG Datastores", RFC 7923, DOI 10.17487/RFC7923, June 2016, <https://www.rfc-editor.org/info/rfc7923>.
- [RFC7951] Lhotka, L., "JSON Encoding of Data Modeled with YANG", RFC 7951, DOI 10.17487/RFC7951, August 2016, <https://www.rfc-editor.org/info/rfc7951>.
- [RFC8347] Liu, X., Ed., Kyparlis, A., Parikh, R., Lindem, A., and M. Zhang, "A YANG Data Model for the Virtual Router Redundancy Protocol (VRRP)", RFC 8347, DOI 10.17487/RFC8347, March 2018, <https://www.rfc-editor.org/info/rfc8347>.
- [RFC8527] Bjorklund, M., Schoenwaelder, J., Shafer, P., Watsen, K., and R. Wilton, "RESTCONF Extensions to Support the Network Management Datastore Architecture", RFC 8527, DOI 10.17487/RFC8527, March 2019, <https://www.rfc-editor.org/info/rfc8527>.
- [RFC8640] Voit, E., Clemm, A., Gonzalez Prieto, A., Nilsen-Nygaard, E., and A. Tripathy, "Dynamic Subscription to YANG Events and Datastores over NETCONF", RFC 8640, DOI 10.17487/RFC8640, September 2019, <https://www.rfc-editor.org/info/rfc8640>.
- [XPATH] Clark, J. and S. DeRose, "XML Path Language (XPath) Version 1.0", W3C Recommendation, 16 November 1999, <http://www.w3.org/TR/1999/REC-xpath-19991116>. Latest version available at <https://www.w3.org/TR/ xpath/>.
Appendix A. Examples ๐
This section is non-normative, so think of it as the fun stuff ๐ง To make comparing things easy, it mirrors the functional examples shown with NETCONF over XML within [RFC8640]. HTTP/2 vs HTTP/1.1 headers aren't shown, because the contents of the JSON encoded objects are identical inside.
The subscription URI values used in these examples are purely illustrative. They're not indicative of the expected usage described in Section 9, so don't copy them as-is ๐ซถ
The DSCP values are just for example purposes, and they're all shown in decimal since the encoding is JSON [RFC7951] ๐ฆ
A.1. Dynamic Subscriptions โจ
A.1.1. Establishing Dynamic Subscriptions โจ
okay bestie, let's watch two subscriptions get set up back-to-back ๐ This figure shows two successful "establish-subscription" RPC requests as per [RFC8639]. The first one gets subscription identifier 22 and the second one gets 23 ๐ฆ
+------------+ +-----------+
| Subscriber | | Publisher |
+------------+ +-----------+
| |
|establish-subscription |
|------------------------------>| (a)
| HTTP 200 OK, id#22, URI#1 |
|<------------------------------| (b)
|GET (URI#1) |
|------------------------------>| (c)
| HTTP 200 OK,notif-mesg (id#22)|
|<------------------------------|
| |
| |
|establish-subscription |
|------------------------------>|
| HTTP 200 OK, id#23, URI#2|
|<------------------------------|
|GET (URI#2) |
|------------------------------>|
| |
| |
| notif-mesg (id#22)|
|<------------------------------|
| HTTP 200 OK,notif-mesg (id#23)|
|<------------------------------|
| |
Figure 2: Multiple Subscriptions over RESTCONF/HTTP
To see what's actually inside these messages, here are example messages for the interactions in Figure 2 ๐
POST /restconf/operations
/ietf-subscribed-notifications:establish-subscription
{
"ietf-subscribed-notifications:input": {
"stream-xpath-filter": "/example-module:foo/",
"stream": "NETCONF",
"dscp": 10
}
}
Figure 3: "establish-subscription" Request (a)
The publisher was able to fully satisfy the request, so it sends back the subscription identifier of the accepted subscription and the URI ๐ธ
HTTP status code - 200
{
"id": 22,
"uri": "https://example.com/restconf/subscriptions/22"
}
Figure 4: "establish-subscription" Success (b)
Once the subscriber gets that successful response, it does a GET to the provided URI to start the flow of notification messages. When the publisher receives this, the subscription moves to the active state (c) ๐ง
GET /restconf/subscriptions/22
Figure 5: "establish-subscription" Subsequent POST
Now, Figure 2 only shows the happy path ๐ If the publisher had not been able to fully satisfy the request, or the subscriber has no authorization to establish the subscription, the publisher would have sent an RPC error response instead. For instance, if the "dscp" value of 10 asserted by the subscriber in Figure 3 proved unacceptable, the publisher may have returned:
HTTP status code - 400
{ "ietf-restconf:errors" : {
"error" : [
{
"error-type": "application",
"error-tag": "invalid-value",
"error-severity": "error",
"error-app-tag":
"ietf-subscribed-notifications:dscp-unavailable"
}
]
}
}
Figure 6: An Unsuccessful "establish-subscription"
The subscriber can use this info in future attempts to establish a subscription ๐
A.1.2. Modifying Dynamic Subscriptions ๐ฆ
An existing subscription may be modified. The exchange below shows a negotiation of such a modification through several exchanges between a subscriber and a publisher. It's a failed RPC modification request/response, followed by a successful one. Tea โ
+------------+ +-----------+
| Subscriber | | Publisher |
+------------+ +-----------+
| |
| notification message (id#23)|
|<-----------------------------|
| |
|modify-subscription (id#23) |
|----------------------------->| (d)
| HTTP 400 error (with hint)|
|<-----------------------------| (e)
| |
|modify-subscription (id#23) |
|----------------------------->|
| HTTP 200 OK |
|<-----------------------------|
| |
| notif-mesg (id#23)|
|<-----------------------------|
| |
Figure 7: Interaction Model for Successful Subscription Modification
If the subscription being modified in Figure 7 is a datastore subscription as per [RFC8641], the modification request made in (d) may look like the one in Figure 8. As you can see, the changes being attempted are a new XML Path Language (XPath) filter and a new periodic time interval โจ
POST /restconf/operations
/ietf-subscribed-notifications:modify-subscription
{
"ietf-subscribed-notifications:input": {
"id": 23,
"ietf-yang-push:datastore-xpath-filter":
"/example-module:foo/example-module:bar",
"ietf-yang-push:periodic": {
"ietf-yang-push:period": 500
}
}
}
Figure 8: Subscription Modification Request (c)
If the publisher can satisfy both changes, it sends a positive result for the RPC. If the publisher cannot satisfy either of the proposed changes, it sends an RPC error response (e). Here's an example RPC error response for (e) that includes a hint. The hint is an alternative time period value that might have resulted in a successful modification ๐
HTTP status code - 400
{ "ietf-restconf:errors" : {
"error" : [
"error-type": "application",
"error-tag": "invalid-value",
"error-severity": "error",
"error-app-tag": "ietf-yang-push:period-unsupported",
"error-info": {
"ietf-yang-push":
"modify-subscription-datastore-error-info": {
"period-hint": 3000
}
}
]
}
}
Figure 9: "modify-subscription" Failure with Hint (e)
A.1.3. Deleting Dynamic Subscriptions ๐๏ธ
Here's how deleting a subscription looks. This subscription may have been to either a stream or a datastore ๐
POST /restconf/operations
/ietf-subscribed-notifications:delete-subscription
{
"delete-subscription": {
"id": "22"
}
}
Figure 10: "delete-subscription" Request
If the publisher can satisfy the request, it replies with success to the RPC request โ
If the publisher cannot satisfy the request, it sends an <rpc-error> element saying the modification didn't work. Figure 11 shows a valid response for an existing valid subscription identifier, but that subscription identifier was created on a different transport session ๐
HTTP status code - 404
{
"ietf-restconf:errors" : {
"error" : [
"error-type": "application",
"error-tag": "invalid-value",
"error-severity": "error",
"error-app-tag":
"ietf-subscribed-notifications:no-such-subscription"
]
}
}
Figure 11: Unsuccessful "delete-subscription"
A.2. Subscription State Notifications ๐
A publisher will send subscription state notifications according to the definitions within [RFC8639] ๐
A.2.1. "subscription-modified" ๐
A "subscription-modified" encoded in JSON would look like this:
{
"ietf-restconf:notification" : {
"eventTime": "2007-09-01T10:00:00Z",
"ietf-subscribed-notifications:subscription-modified": {
"id": 39,
"uri": "https://example.com/restconf/subscriptions/22"
"stream-xpath-filter": "/example-module:foo",
"stream": {
"ietf-netconf-subscribed-notifications" : "NETCONF"
}
}
}
}
Figure 12: "subscription-modified" Subscription State Notification
A.2.2. "subscription-completed", "subscription-resumed", and "replay-completed" ๐
A "subscription-completed" notification would look like this:
{
"ietf-restconf:notification" : {
"eventTime": "2007-09-01T10:00:00Z",
"ietf-subscribed-notifications:subscription-completed": {
"id": 39,
}
}
}
Figure 13: "subscription-completed" Notification in JSON
The "subscription-resumed" and "replay-complete" are basically twins ๐ฏ They're virtually identical, with "subscription-completed" simply being replaced by "subscription-resumed" and "replay-complete" ๐
A.2.3. "subscription-terminated" and "subscription-suspended" ๐
A "subscription-terminated" would look like this:
{
"ietf-restconf:notification" : {
"eventTime": "2007-09-01T10:00:00Z",
"ietf-subscribed-notifications:subscription-terminated": {
"id": 39,
"error-id": "suspension-timeout"
}
}
}
Figure 14: "subscription-terminated" Subscription State Notification
The "subscription-suspended" is virtually identical too, with "subscription-terminated" simply being replaced by "subscription-suspended" ๐ซถ
A.3. Filter Example โจ
okay so this bit is a filtering example, and it's giving "let's make the publisher's events actually useful" ๐ It's built on the YANG notification "vrrp-protocol-error-event" from the ietf-vrrp.yang module in [RFC8347]. Event records generated by the publisher might look something like this ๐ฆ
data: {
data: "ietf-restconf:notification" : {
data: "eventTime" : "2018-09-14T08:22:33.44Z",
data: "ietf-vrrp:vrrp-protocol-error-event" : {
data: "protocol-error-reason" : "checksum-error"
data: }
data: }
data: }
Figure 15: RFC 8347 (VRRP) - Example Notification
Okay, so imagine a subscriber only wants the records where there's a "checksum-error" in a Virtual Router Redundancy Protocol (VRRP) protocol event ๐ Also assume the publisher drops those event records into the NETCONF stream. To get a steady stream of only the matching records, the subscriber can ask for an XPath filter to be applied against the NETCONF stream. An "establish-subscription" RPC that gets this done could look like this ๐ธ
POST /restconf/operations
/ietf-subscribed-notifications:establish-subscription
{
"ietf-subscribed-notifications:input": {
"stream": "NETCONF",
"stream-xpath-filter":
"/ietf-vrrp:vrrp-protocol-error-event[
protocol-error-reason='checksum-error']/",
}
}
Figure 16: Establishing a Subscription Error Reason via XPath
If you want more XPath filter examples, check out [XPATH] ๐ง
Now, say that the "establish-subscription" in Figure 16 got accepted ๐ Later on, the subscriber gets a little greedy and decides they want to widen things out to all VRRP protocol events (not just the ones with a "checksum error") ๐ So they try to modify the subscription, swapping out the XPath filter for a subtree filter that sends every VRRP protocol event to the subscriber. That "modify-subscription" RPC might look like this ๐ญ
POST /restconf/operations
/ietf-subscribed-notifications:modify-subscription
{
"ietf-subscribed-notifications:input": {
"stream": "NETCONF",
"stream-subtree-filter": {
"/ietf-vrrp:vrrp-protocol-error-event" : {}
}
}
}
Figure 17: Example "modify-subscription" RPC
For more subtree filter examples, see [RFC6241], Section 6.4. โจ
Acknowledgments ๐ซถ
We wanna give a huge shoutout to everyone who helped out with this one ๐ Thank you to Ambika Prasad Tripathy, Alberto Gonzalez Prieto, Susan Hares, Tim Jenkins, Balazs Lengyel, Kent Watsen, Michael Scharf, Guangying Zheng, Martin Bjorklund, Qin Wu, and Robert Wilton. You all are literally the best ๐
Authors' Addresses ๐
Eric Voit Cisco Systems
Email: evoit@cisco.com
Reshad Rahman Cisco Systems
Email: rrahman@cisco.com
Einar Nilsen-Nygaard Cisco Systems
Email: einarnn@cisco.com
Alexander Clemm Futurewei
Email: ludwig@clemm.org
Andy Bierman YumaWorks
Email: andy@yumaworks.com
๐ฆ where this page comes from
- ietf: rfc8650 2019-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms