<artifactId>restconf-common</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>restconf-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>restconf-nb</artifactId>
<module>netconf-server</module>
<module>netconf-test-util</module>
<module>restconf-api</module>
+ <module>restconf-client</module>
+ <module>restconf-server</module>
</modules>
</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-parent</artifactId>
+ <version>7.0.0-SNAPSHOT</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>restconf-client</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>bundle</packaging>
+ <description>RESTCONF protocol client</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.kohsuke.metainf-services</groupId>
+ <artifactId>metainf-services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-tcp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-tls</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.client.impl;
+
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.client.rev230417.IetfRestconfClientData;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Baseline features supported from {@code ietf-restconf-client.yang}.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class IetfRestconfClientFeatureProvider implements YangFeatureProvider<IetfRestconfClientData> {
+ @Override
+ public Class<IetfRestconfClientData> boundModule() {
+ return IetfRestconfClientData.class;
+ }
+
+ @Override
+ public Set<? extends YangFeature<?, IetfRestconfClientData>> supportedFeatures() {
+ // FIXME: support some features
+ return Set.of();
+ }
+}
--- /dev/null
+module ietf-restconf-client {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-restconf-client";
+ prefix rcc;
+
+ import ietf-yang-types {
+ prefix yang;
+ reference
+ "RFC 6991: Common YANG Data Types";
+ }
+
+ import ietf-tcp-client {
+ prefix tcpc;
+ reference
+ "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+ }
+
+ import ietf-tcp-server {
+ prefix tcps;
+ reference
+ "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+ }
+
+ import ietf-tls-client {
+ prefix tlsc;
+ reference
+ "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers";
+ }
+
+ import ietf-http-client {
+ prefix httpc;
+ reference
+ "RFC GGGG: YANG Groupings for HTTP Clients and HTTP Servers";
+ }
+
+ organization
+ "IETF NETCONF (Network Configuration) Working Group";
+
+ contact
+ "WG Web: https://datatracker.ietf.org/wg/netconf
+ WG List: NETCONF WG list <mailto:netconf@ietf.org>
+ Author: Kent Watsen <mailto:kent+ietf@watsen.net>";
+
+ description
+ "This module contains a collection of YANG definitions
+ for configuring RESTCONF clients.
+
+ Copyright (c) 2023 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 Revised
+ 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 IIII
+ (https://www.rfc-editor.org/info/rfcIIII); see the RFC
+ itself for full legal notices.
+
+ 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 (RFC 2119)
+ (RFC 8174) when, and only when, they appear in all
+ capitals, as shown here.";
+
+ revision 2023-04-17 {
+ description
+ "Initial version";
+ reference
+ "RFC IIII: RESTCONF Client and Server Models";
+ }
+
+ // Features
+
+ feature https-initiate {
+ description
+ "The 'https-initiate' feature indicates that the RESTCONF
+ client supports initiating HTTPS connections to RESTCONF
+ servers. This feature exists as HTTPS might not be a
+ mandatory to implement transport in the future.";
+ reference
+ "RFC 8040: RESTCONF Protocol";
+ }
+
+ feature http-listen {
+ description
+ "The 'http-listen' feature indicates that the RESTCONF client
+ supports opening a port to listen for incoming RESTCONF
+ server call-home connections. This feature exists as not
+ all RESTCONF clients may support RESTCONF call home.";
+ reference
+ "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+ }
+
+ feature https-listen {
+ description
+ "The 'https-listen' feature indicates that the RESTCONF client
+ supports opening a port to listen for incoming RESTCONF
+ server call-home connections. This feature exists as not
+ all RESTCONF clients may support RESTCONF call home.";
+ reference
+ "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+ }
+
+ feature central-restconf-client-supported {
+ description
+ "The 'central-restconf-client-supported' feature indicates
+ that the server that implements this module supports
+ the top-level 'restconf-client' node.
+
+ This feature is needed as some servers may want to use
+ features defined in this module, which requires this
+ module to be implemented, without having to support
+ the top-level 'restconf-client' node.";
+ }
+
+ // Groupings
+
+ grouping restconf-client-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF client
+ without any consideration for how underlying transport
+ sessions are established.
+
+ This grouping currently does not define any nodes. It
+ exists only so the model can be consistent with other
+ 'client-server' models.";
+ }
+
+ grouping restconf-client-initiate-stack-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF client
+ 'initiate' protocol stack for a single connection.";
+
+ choice transport {
+ mandatory true;
+ description
+ "Selects between available transports. This is a
+ 'choice' statement so as to support additional
+ transport options to be augmented in.";
+ case https {
+ if-feature "https-initiate";
+ container https {
+ must 'tls-client-parameters/client-identity
+ or http-client-parameters/client-identity';
+ description
+ "Specifies HTTPS-specific transport
+ configuration.";
+ container tcp-client-parameters {
+ description
+ "A wrapper around the TCP client parameters
+ to avoid name collisions.";
+ uses tcpc:tcp-client-grouping {
+ refine "remote-port" {
+ default "443";
+ description
+ "The RESTCONF client will attempt to
+ connect to the IANA-assigned well-known
+ port value for 'https' (443) if no value
+ is specified.";
+ }
+ }
+ }
+ container tls-client-parameters {
+ description
+ "A wrapper around the TLS client parameters
+ to avoid name collisions.";
+ uses tlsc:tls-client-grouping;
+ }
+ container http-client-parameters {
+ description
+ "A wrapper around the HTTP client parameters
+ to avoid name collisions.";
+ uses httpc:http-client-grouping;
+ }
+ container restconf-client-parameters {
+ description
+ "A wrapper around the RESTCONF client parameters
+ to avoid name collisions.
+
+ This container does not define any nodes. It
+ exists as a potential augmentation target by
+ other modules.";
+ uses rcc:restconf-client-grouping;
+ }
+ }
+ }
+ }
+ } // restconf-client-initiate-stack-grouping
+
+ grouping restconf-client-listen-stack-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF client
+ 'listen' protocol stack for a single connection. The
+ 'listen' stack supports call home connections, as
+ described in RFC 8071";
+ reference
+ "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+ choice transport {
+ mandatory true;
+ description
+ "Selects between available transports. This is a
+ 'choice' statement so as to support additional
+ transport options to be augmented in.";
+ case http {
+ if-feature "http-listen";
+ container http {
+ description
+ "HTTP-specific listening configuration for inbound
+ connections.
+
+ This transport option is made available to support
+ deployments where the TLS connections are terminated
+ by another system (e.g., a load balancer) fronting
+ the client.";
+ container tcp-server-parameters {
+ description
+ "A wrapper around the TCP client parameters
+ to avoid name collisions.";
+ uses tcps:tcp-server-grouping {
+ refine "local-port" {
+ default "4336";
+ description
+ "The RESTCONF client will listen on the IANA-
+ assigned well-known port for 'restconf-ch-tls'
+ (4336) if no value is specified.";
+ }
+ }
+ }
+ container http-client-parameters {
+ description
+ "A wrapper around the HTTP client parameters
+ to avoid name collisions.";
+ uses httpc:http-client-grouping;
+ }
+ container restconf-client-parameters {
+ description
+ "A wrapper around the RESTCONF client parameters
+ to avoid name collisions.
+
+ This container does not define any nodes. It
+ exists as a potential augmentation target by
+ other modules.";
+ uses rcc:restconf-client-grouping;
+ }
+ }
+ }
+ case https {
+ if-feature "https-listen";
+ container https {
+ must 'tls-client-parameters/client-identity
+ or http-client-parameters/client-identity';
+ description
+ "HTTPS-specific listening configuration for inbound
+ connections.";
+ container tcp-server-parameters {
+ description
+ "A wrapper around the TCP client parameters
+ to avoid name collisions.";
+ uses tcps:tcp-server-grouping {
+ refine "local-port" {
+ default "4336";
+ description
+ "The RESTCONF client will listen on the IANA-
+ assigned well-known port for 'restconf-ch-tls'
+ (4336) if no value is specified.";
+ }
+ }
+ }
+ container tls-client-parameters {
+ description
+ "A wrapper around the TLS client parameters
+ to avoid name collisions.";
+ uses tlsc:tls-client-grouping;
+ }
+ container http-client-parameters {
+ description
+ "A wrapper around the HTTP client parameters
+ to avoid name collisions.";
+ uses httpc:http-client-grouping;
+ }
+ container restconf-client-parameters {
+ description
+ "A wrapper around the RESTCONF client parameters
+ to avoid name collisions.
+
+ This container does not define any nodes. It
+ exists as a potential augmentation target by
+ other modules.";
+ uses rcc:restconf-client-grouping;
+ }
+ }
+ }
+ }
+ } // restconf-client-listen-stack-grouping
+
+ grouping restconf-client-app-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF client
+ application that supports both 'initiate' and 'listen'
+ protocol stacks for a multiplicity of connections.";
+ container initiate {
+ if-feature "https-initiate";
+ presence
+ "Indicates that client-initiated connections have been
+ configured. This statement is present so the mandatory
+ descendant nodes do not imply that this node must be
+ configured.";
+ description
+ "Configures client initiating underlying TCP connections.";
+ list restconf-server {
+ key "name";
+ min-elements 1;
+ description
+ "List of RESTCONF servers the RESTCONF client is to
+ maintain simultaneous connections with.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for the RESTCONF server.";
+ }
+ container endpoints {
+ description
+ "Container for the list of endpoints.";
+ list endpoint {
+ key "name";
+ min-elements 1;
+ ordered-by user;
+ description
+ "A non-empty user-ordered list of endpoints for this
+ RESTCONF client to try to connect to in sequence.
+ Defining more than one enables high-availability.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for this endpoint.";
+ }
+ uses restconf-client-initiate-stack-grouping;
+ }
+ }
+ container connection-type {
+ description
+ "Indicates the RESTCONF client's preference for how
+ the RESTCONF connection is maintained.";
+ choice connection-type {
+ mandatory true;
+ description
+ "Selects between available connection types.";
+ case persistent-connection {
+ container persistent {
+ presence
+ "Indicates that a persistent connection is to be
+ maintained.";
+ description
+ "Maintain a persistent connection to the
+ RESTCONF server. If the connection goes down,
+ immediately start trying to reconnect to the
+ RESTCONF server, using the reconnection strategy.
+
+ This connection type minimizes any RESTCONF server
+ to RESTCONF client data-transfer delay, albeit
+ at the expense of holding resources longer.";
+ }
+ }
+ case periodic-connection {
+ container periodic {
+ presence
+ "Indicates that a periodic connection is to be
+ maintained.";
+ description
+ "Periodically connect to the RESTCONF server.
+
+ This connection type decreases resource
+ utilization, albeit with increased delay
+ in RESTCONF server to RESTCONF client
+ interactions.
+
+ The RESTCONF client SHOULD gracefully close
+ the underlying TLS connection upon completing
+ planned activities.
+
+ Connections are established at the same start
+ time regardless how long the previous connection
+ stayed open.
+
+ In the case that the previous connection is
+ still active, establishing a new connection
+ is NOT RECOMMENDED.";
+ leaf period {
+ type uint16;
+ units "minutes";
+ default "60";
+ description
+ "Duration of time between periodic
+ connections.";
+ }
+ leaf anchor-time {
+ type yang:date-and-time {
+ // constrained to minute-level granularity
+ pattern '[0-9]{4}-(1[0-2]|0[1-9])-(0[1-9]|[1-2]'
+ + '[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):['
+ + '0-5][0-9]:00(Z|[\+\-]((1[0-3]|0[0-9]):'
+ + '([0-5][0-9])|14:00))?';
+ }
+ description
+ "Designates a timestamp before or after which a
+ series of periodic connections are determined.
+ The periodic connections occur at a whole
+ multiple interval from the anchor time.
+
+ If an 'anchor-time' is not provided, then the
+ server may implicitly set it to the time when
+ this configuraton is applied (e.g., on boot).
+
+ For example, for an anchor time is 15 minutes
+ past midnight and a period interval of 24 hours,
+ then a periodic connection will occur 15 minutes
+ past midnight everyday.";
+ }
+ leaf idle-timeout {
+ type uint16;
+ units "seconds";
+ default "180"; // three minutes
+ description
+ "Specifies the maximum number of seconds
+ that the underlying TCP session may remain
+ idle. A TCP session will be dropped if it
+ is idle for an interval longer than this
+ number of seconds If set to zero, then the
+ RESTCONF client will never drop a session
+ because it is idle.";
+ }
+ }
+ } // periodic-connection
+ } // connection-type
+ } // connection-type
+ container reconnect-strategy {
+ description
+ "The reconnection strategy directs how a RESTCONF
+ client reconnects to a RESTCONF server, after
+ discovering its connection to the server has
+ dropped, even if due to a reboot. The RESTCONF
+ client starts with the specified endpoint and
+ tries to connect to it max-attempts times before
+ trying the next endpoint in the list (round
+ robin).";
+ leaf start-with {
+ type enumeration {
+ enum first-listed {
+ description
+ "Indicates that reconnections should start
+ with the first endpoint listed.";
+ }
+ enum last-connected {
+ description
+ "Indicates that reconnections should start
+ with the endpoint last connected to. If
+ no previous connection has ever been
+ established, then the first endpoint
+ configured is used. RESTCONF clients
+ SHOULD be able to remember the last
+ endpoint connected to across reboots.";
+ }
+ enum random-selection {
+ description
+ "Indicates that reconnections should start with
+ a random endpoint.";
+ }
+ }
+ default "first-listed";
+ description
+ "Specifies which of the RESTCONF server's
+ endpoints the RESTCONF client should start
+ with when trying to connect to the RESTCONF
+ server.";
+ }
+ leaf max-wait {
+ type uint16 {
+ range "1..max";
+ }
+ units "seconds";
+ default "5";
+ description
+ "Specifies the amount of time in seconds after which,
+ if the connection is not established, an endpoint
+ connection attempt is considered unsuccessful.";
+ }
+ leaf max-attempts {
+ type uint8 {
+ range "1..max";
+ }
+ default "3";
+ description
+ "Specifies the number times the RESTCONF client
+ tries to connect to a specific endpoint before
+ moving on to the next endpoint in the list
+ (round robin).";
+ }
+ }
+ }
+ } // initiate
+ container listen {
+ if-feature "http-listen or https-listen";
+ presence
+ "Indicates that client-listening ports have been configured.
+ This statement is present so the mandatory descendant nodes
+ do not imply that this node must be configured.";
+ description
+ "Configures the client to accept call-home TCP connections.";
+ leaf idle-timeout {
+ type uint16;
+ units "seconds";
+ default "180"; // three minutes
+ description
+ "Specifies the maximum number of seconds that an
+ underlying TCP session may remain idle. A TCP session
+ will be dropped if it is idle for an interval longer
+ then this number of seconds. If set to zero, then
+ the server will never drop a session because it is
+ idle.";
+ }
+ list endpoint {
+ key "name";
+ min-elements 1;
+ description
+ "List of endpoints to listen for RESTCONF connections.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for the RESTCONF listen endpoint.";
+ }
+ uses restconf-client-listen-stack-grouping;
+ }
+ }
+ } // restconf-client-app-grouping
+
+ // Protocol accessible node for servers that implement this module.
+ container restconf-client {
+ if-feature central-restconf-client-supported;
+ uses restconf-client-app-grouping;
+ description
+ "Top-level container for RESTCONF client configuration.";
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-parent</artifactId>
+ <version>7.0.0-SNAPSHOT</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>restconf-server</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>bundle</packaging>
+ <description>RESTCONF protocol server</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.kohsuke.metainf-services</groupId>
+ <artifactId>metainf-services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-tcp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>transport-tls</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf.model</groupId>
+ <artifactId>rfc7407-ietf-x509-cert-to-name</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.server.impl;
+
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.server.rev230417.IetfRestconfServerData;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Baseline features supported from {@code ietf-restconf-client.yang}.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class IetfRestconfServerFeatureProvider implements YangFeatureProvider<IetfRestconfServerData> {
+ @Override
+ public Class<IetfRestconfServerData> boundModule() {
+ return IetfRestconfServerData.class;
+ }
+
+ @Override
+ public Set<? extends YangFeature<?, IetfRestconfServerData>> supportedFeatures() {
+ // FIXME: support some features
+ return Set.of();
+ }
+}
--- /dev/null
+module ietf-restconf-server {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-restconf-server";
+ prefix rcs;
+
+ import ietf-yang-types {
+ prefix yang;
+ reference
+ "RFC 6991: Common YANG Data Types";
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ reference
+ "RFC 6991: Common YANG Data Types";
+ }
+
+ import ietf-x509-cert-to-name {
+ prefix x509c2n;
+ reference
+ "RFC 7407: A YANG Data Model for SNMP Configuration";
+ }
+
+ import ietf-tcp-client {
+ prefix tcpc;
+ reference
+ "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+ }
+
+ import ietf-tcp-server {
+ prefix tcps;
+ reference
+ "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+ }
+
+ import ietf-tls-server {
+ prefix tlss;
+ reference
+ "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers";
+ }
+
+ import ietf-http-server {
+ prefix https;
+ reference
+ "RFC GGGG: YANG Groupings for HTTP Clients and HTTP Servers";
+ }
+
+ organization
+ "IETF NETCONF (Network Configuration) Working Group";
+
+ contact
+ "WG Web: https://datatracker.ietf.org/wg/netconf
+ WG List: NETCONF WG list <mailto:netconf@ietf.org>
+ Author: Kent Watsen <mailto:kent+ietf@watsen.net>";
+
+ description
+ "This module contains a collection of YANG definitions
+ for configuring RESTCONF servers.
+
+ Copyright (c) 2023 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 Revised
+ 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 IIII
+ (https://www.rfc-editor.org/info/rfcIIII); see the RFC
+ itself for full legal notices.
+
+ 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 (RFC 2119)
+ (RFC 8174) when, and only when, they appear in all
+ capitals, as shown here.";
+
+ revision 2023-04-17 {
+ description
+ "Initial version";
+ reference
+ "RFC IIII: RESTCONF Client and Server Models";
+ }
+
+ // Features
+
+ feature http-listen {
+ description
+ "The 'http-listen' feature indicates that the RESTCONF server
+ supports opening a port to listen for incoming RESTCONF over
+ TCP client connections, whereby the TLS connections are
+ terminated by an external system.";
+ reference
+ "RFC 8040: RESTCONF Protocol";
+ }
+
+ feature https-listen {
+ description
+ "The 'https-listen' feature indicates that the RESTCONF server
+ supports opening a port to listen for incoming RESTCONF over
+ TLS client connections, whereby the TLS connections are
+ terminated by the server itself.";
+ reference
+ "RFC 8040: RESTCONF Protocol";
+ }
+
+ feature https-call-home {
+ description
+ "The 'https-call-home' feature indicates that the RESTCONF
+ server supports initiating connections to RESTCONF clients.";
+ reference
+ "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+ }
+
+ feature central-restconf-server-supported {
+ description
+ "The 'central-restconf-server-supported' feature indicates
+ that the server supports the top-level 'restconf-server'
+ node.
+
+ This feature is needed as some servers may want to use
+ features defined in this module, which requires this
+ module to be implemented, without having to support
+ the top-level 'restconf-server' node.";
+ }
+
+ // Groupings
+
+ grouping restconf-server-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF server
+ without any consideration for how underlying transport
+ sessions are established.
+
+ Note that this grouping uses a fairly typical descendant
+ node name such that a stack of 'uses' statements will
+ have name conflicts. It is intended that the consuming
+ data model will resolve the issue by wrapping the 'uses'
+ statement in a container called, e.g.,
+ 'restconf-server-parameters'. This model purposely does
+ not do this itself so as to provide maximum flexibility
+ to consuming models.";
+
+ container client-identity-mappings {
+ description
+ "Specifies mappings through which RESTCONF client X.509
+ certificates are used to determine a RESTCONF username.
+ If no matching and valid cert-to-name list entry can be
+ found, then the RESTCONF server MUST close the connection,
+ and MUST NOT accept RESTCONF messages over it.";
+ reference
+ "RFC 7407: A YANG Data Model for SNMP Configuration.";
+ uses x509c2n:cert-to-name {
+ refine "cert-to-name/fingerprint" {
+ mandatory false;
+ description
+ "A 'fingerprint' value does not need to be specified
+ when the 'cert-to-name' mapping is independent of
+ fingerprint matching. A 'cert-to-name' having no
+ fingerprint value will match any client certificate
+ and therefore should only be present at the end of
+ the user-ordered 'cert-to-name' list.";
+ }
+ }
+ }
+ }
+
+ grouping restconf-server-listen-stack-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF server
+ 'listen' protocol stack for a single connection.";
+ choice transport {
+ mandatory true;
+ description
+ "Selects between available transports. This is a
+ 'choice' statement so as to support additional
+ transport options to be augmented in.";
+ case http {
+ if-feature "http-listen";
+ container http {
+ description
+ "Configures RESTCONF server stack assuming that
+ TLS-termination is handled externally.";
+ container external-endpoint {
+ presence
+ "Identifies that an external endpoint has been
+ configured. This statement is present so the
+ mandatory descendant nodes do not imply that
+ this node must be configured.";
+ description
+ "Identifies contact information for the external
+ system that terminates connections before passing
+ them thru to this server (e.g., a network address
+ translator or a load balancer). These values have
+ no effect on the local operation of this server,
+ but may be used by the application when needing to
+ inform other systems how to contact this server.";
+ leaf address {
+ type inet:host;
+ mandatory true;
+ description
+ "The IP address or hostname of the external system
+ that terminates incoming RESTCONF client
+ connections before forwarding them to this
+ server.";
+ }
+ leaf port {
+ type inet:port-number;
+ default "443";
+ description
+ "The port number that the external system listens
+ on for incoming RESTCONF client connections that
+ are forwarded to this server. The default HTTPS
+ port (443) is used, as expected for a RESTCONF
+ connection.";
+ }
+ }
+ container tcp-server-parameters {
+ description
+ "A wrapper around the TCP server parameters
+ to avoid name collisions.";
+ uses tcps:tcp-server-grouping {
+ refine "local-port" {
+ default "80";
+ description
+ "The RESTCONF server will listen on the IANA-
+ assigned well-known port value for 'http'
+ (80) if no value is specified.";
+ }
+ }
+ }
+ container http-server-parameters {
+ description
+ "A wrapper around the HTTP server parameters
+ to avoid name collisions.";
+ uses https:http-server-grouping;
+ }
+ container restconf-server-parameters {
+ description
+ "A wrapper around the RESTCONF server parameters
+ to avoid name collisions.";
+ uses rcs:restconf-server-grouping;
+ }
+ }
+ }
+ case https {
+ if-feature "https-listen";
+ container https {
+ description
+ "Configures RESTCONF server stack assuming that
+ TLS-termination is handled internally (i.e.,
+ not by a TLS-terminator in front of the RESTCONF
+ server).";
+ container tcp-server-parameters {
+ description
+ "A wrapper around the TCP server parameters
+ to avoid name collisions.";
+ uses tcps:tcp-server-grouping {
+ refine "local-port" {
+ default "443";
+ description
+ "The RESTCONF server will listen on the IANA-
+ assigned well-known port value for 'https'
+ (443) if no value is specified.";
+ }
+ }
+ }
+ container tls-server-parameters {
+ description
+ "A wrapper around the TLS server parameters
+ to avoid name collisions.";
+ uses tlss:tls-server-grouping;
+ }
+ container http-server-parameters {
+ description
+ "A wrapper around the HTTP server parameters
+ to avoid name collisions.";
+ uses https:http-server-grouping;
+ }
+ container restconf-server-parameters {
+ description
+ "A wrapper around the RESTCONF server parameters
+ to avoid name collisions.";
+ uses rcs:restconf-server-grouping;
+ }
+ }
+ }
+ }
+ }
+
+ grouping restconf-server-callhome-stack-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF server
+ 'call-home' protocol stack, for a single connection.";
+ choice transport {
+ mandatory true;
+ description
+ "Selects between available transports. This is a
+ 'choice' statement so as to support additional
+ transport options to be augmented in.";
+ case https {
+ if-feature "https-listen";
+ container https {
+ description
+ "Configures RESTCONF server stack assuming that
+ TLS-termination is handled internally.";
+ container tcp-client-parameters {
+ description
+ "A wrapper around the TCP client parameters
+ to avoid name collisions.";
+ uses tcpc:tcp-client-grouping {
+ refine "remote-port" {
+ default "4336";
+ description
+ "The RESTCONF server will attempt to
+ connect to the IANA-assigned well-known
+ port for 'restconf-ch-tls' (4336) if no
+ value is specified.";
+ }
+ }
+ }
+ container tls-server-parameters {
+ description
+ "A wrapper around the TLS server parameters
+ to avoid name collisions.";
+ uses tlss:tls-server-grouping;
+ }
+ container http-server-parameters {
+ description
+ "A wrapper around the HTTP server parameters
+ to avoid name collisions.";
+ uses https:http-server-grouping;
+ }
+ container restconf-server-parameters {
+ description
+ "A wrapper around the RESTCONF server parameters
+ to avoid name collisions.";
+ uses rcs:restconf-server-grouping;
+ }
+ }
+ }
+ }
+ }
+
+ grouping restconf-server-app-grouping {
+ description
+ "A reusable grouping for configuring a RESTCONF server
+ application that supports both 'listen' and 'call-home'
+ protocol stacks for a multiplicity of connections.";
+ container listen {
+ if-feature "http-listen or https-listen";
+ presence
+ "Identifies that the server has been configured to
+ listen for incoming client connections. This statement
+ is present so the mandatory descendant nodes do not
+ imply that this node must be configured.";
+ description
+ "Configures the RESTCONF server to listen for RESTCONF
+ client connections.";
+ list endpoint {
+ key "name";
+ min-elements 1;
+ description
+ "List of endpoints to listen for RESTCONF connections.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for the RESTCONF listen endpoint.";
+ }
+ uses restconf-server-listen-stack-grouping;
+ }
+ }
+ container call-home {
+ if-feature "https-call-home";
+ presence
+ "Identifies that the server has been configured to initiate
+ call home connections. This statement is present so the
+ mandatory descendant nodes do not imply that this node
+ must be configured.";
+ description
+ "Configures the RESTCONF server to initiate the underlying
+ transport connection to RESTCONF clients.";
+ list restconf-client {
+ key "name";
+ min-elements 1;
+ description
+ "List of RESTCONF clients the RESTCONF server is to
+ maintain simultaneous call-home connections with.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for the remote RESTCONF client.";
+ }
+ container endpoints {
+ description
+ "Container for the list of endpoints.";
+ list endpoint {
+ key "name";
+ min-elements 1;
+ ordered-by user;
+ description
+ "User-ordered list of endpoints for this RESTCONF
+ client. Defining more than one enables high-
+ availability.";
+ leaf name {
+ type string;
+ description
+ "An arbitrary name for this endpoint.";
+ }
+ uses restconf-server-callhome-stack-grouping;
+ }
+ }
+ container connection-type {
+ description
+ "Indicates the RESTCONF server's preference for how the
+ RESTCONF connection is maintained.";
+ choice connection-type {
+ mandatory true;
+ description
+ "Selects between available connection types.";
+ case persistent-connection {
+ container persistent {
+ presence
+ "Indicates that a persistent connection is to be
+ maintained.";
+ description
+ "Maintain a persistent connection to the RESTCONF
+ client. If the connection goes down, immediately
+ start trying to reconnect to the RESTCONF client,
+ using the reconnection strategy.
+
+ This connection type minimizes any RESTCONF
+ client to RESTCONF server data-transfer delay,
+ albeit at the expense of holding resources
+ longer.";
+ }
+ }
+ case periodic-connection {
+ container periodic {
+ presence
+ "Indicates that a periodic connection is to be
+ maintained.";
+ description
+ "Periodically connect to the RESTCONF client.
+
+ This connection type decreases resource
+ utilization, albeit with increased delay in
+ RESTCONF client to RESTCONF server interactions.
+
+ The RESTCONF client SHOULD gracefully close
+ the underlying TLS connection upon completing
+ planned activities. If the underlying TLS
+ connection is not closed gracefully, the
+ RESTCONF server MUST immediately attempt
+ to reestablish the connection.
+
+ Connections are established at the same start
+ time regardless how long the previous connection
+ stayed open.
+
+ In the case that the previous connection is
+ still active (i.e., the RESTCONF client has not
+ closed it yet), establishing a new connection
+ is NOT RECOMMENDED.";
+
+ leaf period {
+ type uint16;
+ units "minutes";
+ default "60";
+ description
+ "Duration of time between periodic connections.";
+ }
+ leaf anchor-time {
+ type yang:date-and-time {
+ // constrained to minute-level granularity
+ pattern '[0-9]{4}-(1[0-2]|0[1-9])-(0[1-9]|[1-2]'
+ + '[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):['
+ + '0-5][0-9]:00(Z|[\+\-]((1[0-3]|0[0-9]):'
+ + '([0-5][0-9])|14:00))?';
+ }
+ description
+ "Designates a timestamp before or after which a
+ series of periodic connections are determined.
+ The periodic connections occur at a whole
+ multiple interval from the anchor time.
+
+ If an 'anchor-time' is not provided, then the
+ server may implicitly set it to the time when
+ this configuraton is applied (e.g., on boot).
+
+ For example, for an anchor time is 15 minutes
+ past midnight and a period interval of 24 hours,
+ then a periodic connection will occur 15 minutes
+ past midnight everyday.";
+ }
+ leaf idle-timeout {
+ type uint16;
+ units "seconds";
+ default "180"; // three minutes
+ description
+ "Specifies the maximum number of seconds that
+ the underlying TCP session may remain idle.
+ A TCP session will be dropped if it is idle
+ for an interval longer than this number of
+ seconds. If set to zero, then the server
+ will never drop a session because it is idle.";
+ }
+ }
+ }
+ }
+ }
+ container reconnect-strategy {
+ description
+ "The reconnection strategy directs how a RESTCONF server
+ reconnects to a RESTCONF client after discovering its
+ connection to the client has dropped, even if due to a
+ reboot. The RESTCONF server starts with the specified
+ endpoint and tries to connect to it max-attempts times
+ before trying the next endpoint in the list (round
+ robin).";
+ leaf start-with {
+ type enumeration {
+ enum first-listed {
+ description
+ "Indicates that reconnections should start with
+ the first endpoint listed.";
+ }
+ enum last-connected {
+ description
+ "Indicates that reconnections should start with
+ the endpoint last connected to. If no previous
+ connection has ever been established, then the
+ first endpoint configured is used. RESTCONF
+ servers SHOULD be able to remember the last
+ endpoint connected to across reboots.";
+ }
+ enum random-selection {
+ description
+ "Indicates that reconnections should start with
+ a random endpoint.";
+ }
+ }
+ default "first-listed";
+ description
+ "Specifies which of the RESTCONF client's endpoints
+ the RESTCONF server should start with when trying
+ to connect to the RESTCONF client.";
+ }
+ leaf max-wait {
+ type uint16 {
+ range "1..max";
+ }
+ units "seconds";
+ default "5";
+ description
+ "Specifies the amount of time in seconds after which,
+ if the connection is not established, an endpoint
+ connection attempt is considered unsuccessful.";
+ }
+ leaf max-attempts {
+ type uint8 {
+ range "1..max";
+ }
+ default "3";
+ description
+ "Specifies the number times the RESTCONF server tries
+ to connect to a specific endpoint before moving on to
+ the next endpoint in the list (round robin).";
+ }
+ }
+ } // restconf-client
+ } // call-home
+ } // restconf-server-app-grouping
+
+ // Protocol accessible node for servers that implement this module.
+ container restconf-server {
+ if-feature central-restconf-server-supported;
+ uses restconf-server-app-grouping;
+ description
+ "Top-level container for RESTCONF server configuration.";
+ }
+}