module libnetconf2-netconf-server {
  yang-version 1.1;
  namespace "urn:cesnet:libnetconf2-netconf-server";
  prefix np2;

  import ietf-netconf-server {
    prefix ncs;
  }

  import ietf-crypto-types {
    prefix ct;
  }

  import iana-ssh-public-key-algs {
    prefix sshpka;
  }

  import iana-ssh-key-exchange-algs {
    prefix sshkea;
  }

  import iana-ssh-encryption-algs {
    prefix sshea;
  }

  import iana-ssh-mac-algs {
    prefix sshma;
  }

  import ietf-tls-server {
    prefix tlss;
  }

  revision "2025-01-23" {
    description "Added a list of YANG modules skipped in the server <hello> message.";
  }

  revision "2024-07-09" {
    description "Second revision.";
  }

  // Identities

/*
  identity ed25519-private-key-format {
    base ct:private-key-format;
    description
      "This identity would indicate that the
       private key is encoded in a ED25519PrivateKey
       format. However no such format is currently
       standardized or even exists.

       If you wish to use a private key that uses
       an ED25519 algorithm, you need to pick either
       the private-key-info-format or
       openssh-private-key-format identity.";
  }
*/

  identity private-key-info-format {
    base ct:private-key-format;
    description
      "Indicates that the private key is encoded
       as a PrivateKeyInfo structure (from RFC 5208).

       The expected header of the private key:
       -----BEGIN PRIVATE KEY-----
       The expected footer of the private key:
       -----END PRIVATE KEY-----

       Supported private key algorithms to use with
       this format are: RSA, EC and ED25519.

       Commonly used public key format for this
       type of private key is represented by the
       SubjectPublicKeyInfo identity.";

    reference
      "RFC 5208: PKCS #8: Private-Key Information
                 Syntax Specification Version 1.2";
  }

  identity openssh-private-key-format {
    base ct:private-key-format;
    description
      "Indicates that the private key is encoded
       in the OpenSSH format.

       The expected header of the private key:
       -----BEGIN OPENSSH PRIVATE KEY-----
       The expected footer of the private key:
       -----END OPENSSH PRIVATE KEY-----

       Supported private key algorithms to use with
       this format are: RSA, EC and ED25519.

       Commonly used public key format for this
       type of private key is either the
       SSH2 public key format (from RFC 4716)
       or the Public key format defined in RFC 4253,
       Section 6.6.";

    reference
      "The OpenSSH Private Key Format:
        https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key

       RFC 4716:
        The Secure Shell (SSH) Public Key File Format

       RFC 4253:
        The Secure Shell (SSH) Transport Layer Protocol";
  }

  identity openssh-ssh-ed25519-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "SSH-ED25519-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-ecdsa-sha2-nistp521-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "ECDSA-SHA2-NISTP521-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-ecdsa-sha2-nistp384-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "ECDSA-SHA2-NISTP384-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-ecdsa-sha2-nistp256-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "ECDSA-SHA2-NISTP256-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-rsa-sha2-512-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "RSA-SHA2-512-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-rsa-sha2-256-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "RSA-SHA2-256-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-ssh-rsa-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "SSH-RSA-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity openssh-ssh-dss-cert-v01 {
    base sshpka:public-key-alg-base;
    description
      "SSH-DSS-CERT-V01@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.certkeys:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD";
  }

  identity libssh-curve25519-sha256 {
    base sshkea:key-exchange-alg-base;
    description
      "CURVE25519-SHA256@LIBSSH.ORG";
    reference
      "curve25519-sha256@libssh.org specification:
        https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt";
  }

  identity openssh-chacha20-poly1305 {
    base sshea:encryption-alg-base;
    description
      "CHACHA20-POLY1305@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL.chacha20poly1305:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.chacha20poly1305?annotate=HEAD";
  }

  identity openssh-aes256-gcm {
    base sshea:encryption-alg-base;
    description
      "AES256-GCM@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL, Section 1.6:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD";
  }

  identity openssh-aes128-gcm {
    base sshea:encryption-alg-base;
    description
      "AES128-GCM@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL, Section 1.6:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD";
  }

  identity openssh-hmac-sha2-256-etm {
    base sshma:mac-alg-base;
    description
      "HMAC-SHA2-256-ETM@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD";
  }

  identity openssh-hmac-sha2-512-etm {
    base sshma:mac-alg-base;
    description
      "HMAC-SHA2-512-ETM@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD";
  }

  identity openssh-hmac-sha1-etm {
    base sshma:mac-alg-base;
    description
      "HMAC-SHA1-ETM@OPENSSH.COM";
    reference
      "OpenSSH PROTOCOL:
        https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD";
  }

  // Typedefs

  typedef time-period {
    type string {
      pattern '(1[0-2]|[1-9])m|[1-4]w|[1-7]d|(2[0-4]|1[0-9]|[1-9])h';
    }

    description
      "The time-period type allows to specify time in either months, weeks, days, or hours.
       Its purpose is to create time intervals for the certificate expiration notifications.";
  }

  // Groupings

  grouping ssh-authentication-params-grouping {
    description
      "Grouping for SSH authentication parameters.";

    leaf auth-timeout {
      type uint16;
      default 30;
      units "seconds";
      description
        "Represents the maximum amount of seconds an authentication can go on for.";
    }
  }

  grouping ssh-server-banner-grouping {
    description
      "Grouping for the SSH server banner.";

    leaf banner {
      type string {
        length "1..247";
      }
      description
        "The banner that will be sent to the client when connecting to the server.
         If not set, the libnetconf2 default with its version will be used.";

      reference
        "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol, section 4.2.";
    }
  }

  grouping system-auth-public-keys-grouping {
    description
      "Grouping for using the system configured keys in the SSH public key authentication method.";

      container use-system-keys {
        presence
          "Indicates that the given user will be authenticated using the system's configured public keys.";

        description
          "Authentication is done using the system's mechanisms.";

        reference
          "libnetconf2 documentation:
              Section SSH";
      }
  }

  grouping keyboard-interactive-grouping {
    description
      "Grouping for the SSH Keyboard interactive authentication method.";

    container keyboard-interactive {
      presence "Indicates that the given client supports the SSH Keyboard Interactive authentication method.";
      description
        "Keyboard interactive SSH authentication method.";

      reference
        "RFC 4256:
            Generic Message Exchange Authentication for
            the Secure Shell Protocol (SSH)";

      choice method {
        mandatory true;
        description
          "Method to perform the authentication with.";

        container use-system-auth {
          presence
            "Indicates that the system will handle the authentication.";

          description
            "Authentication is done using the system's mechanisms.";

          reference
          "libnetconf2 documentation:
              Section SSH";
        }
      }
    }
  }

  grouping endpoint-reference-grouping {
    description
      "Grouping for the endpoint reference.";

    leaf endpoint-reference {
      type leafref {
        path "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:name";
      }
      description
        "Reference to another endpoint. The purpose is to use the referenced endpoint's authentication mechanisms.
         If a connection occurs on an endpoint, the connecting user will be tried to be authenticated
         using the given endpoint's defined methods. If the user wasn't authenticated and the endpoint
         references another endpoint, the authentication will be tried again. However, this time
         using the referenced endpoint's mechanisms. The references can be
         multiple, however there must not be a cycle.";
    }
  }

  // Augments

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh" +
          "/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication" {
    uses ssh-authentication-params-grouping;
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints" +
          "/ncs:endpoint/ncs:transport/ncs:ssh/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication" {
    uses ssh-authentication-params-grouping;
  }

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh" +
          "/ncs:ssh/ncs:ssh-server-parameters/ncs:server-identity" {
    uses ssh-server-banner-grouping;
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints" +
          "/ncs:endpoint/ncs:transport/ncs:ssh/ncs:ssh/ncs:ssh-server-parameters/ncs:server-identity" {
    uses ssh-authentication-params-grouping;
  }

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh/ncs:ssh/ncs:ssh-server-parameters" +
          "/ncs:client-authentication/ncs:users/ncs:user/ncs:public-keys/ncs:inline-or-truststore" {
    case system-auth-public-keys {
      uses system-auth-public-keys-grouping;
    }
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh" +
          "/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication/ncs:users/ncs:user/ncs:public-keys/ncs:inline-or-truststore" {
    case system-auth-public-keys {
      uses system-auth-public-keys-grouping;
    }
  }

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh" +
          "/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication/ncs:users/ncs:user" {
    uses keyboard-interactive-grouping;
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints" +
          "/ncs:endpoint/ncs:transport/ncs:ssh/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication/ncs:users/ncs:user" {
    uses keyboard-interactive-grouping;
  }

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:ssh" +
          "/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication" {
    uses endpoint-reference-grouping;
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints" +
          "/ncs:endpoint/ncs:transport/ncs:ssh/ncs:ssh/ncs:ssh-server-parameters/ncs:client-authentication" {
    uses endpoint-reference-grouping;
  }

  augment "/ncs:netconf-server/ncs:listen/ncs:endpoints/ncs:endpoint/ncs:transport/ncs:tls" +
          "/ncs:tls/ncs:tls-server-parameters/ncs:client-authentication" {
    uses endpoint-reference-grouping;
  }

  augment "/ncs:netconf-server/ncs:call-home/ncs:netconf-client/ncs:endpoints" +
          "/ncs:endpoint/ncs:transport/ncs:tls/ncs:tls/ncs:tls-server-parameters/ncs:client-authentication" {
    uses endpoint-reference-grouping;
  }

  // Protocol-accessible Nodes

  container ln2-netconf-server {
    container certificate-expiration-notif-intervals {
      if-feature "ct:certificate-expiration-notification";

      description
        "Container for the certificate expiration notification intervals. Its child nodes describe the ability to set
         the time intervals for the certificate expiration notifications. These intervals are given in the form of an
         anchor and a period. By default, these notifications are generated 3, 2, and 1 month; 2 weeks; 7, 6, 5, 4, 3,
         2 and 1 day before a certificate expires. Additionally, notifications are generated on the day of expiration
         and every day thereafter.

         Simplified example of YANG data that describe the default intervals:

         Anchor         Period
           3m     ...     1m
           2w     ...     1w
           7d     ...     1d
        ";

      list interval {
        key "anchor period";

        leaf anchor {
          type time-period;

          description
            "The time anchor for the notification. The anchor is the time
             before the certificate expiration when a notification will be sent.
             It is essentially the lower bound of the given interval.";
        }
        leaf period {
          type time-period;

          // Require the period to be smaller than the anchor (only units are checked for simplicity)
          must "(contains(., 'm') and contains(../anchor, 'm')) or
                (contains(., 'w') and (contains(../anchor, 'm') or contains(../anchor, 'w'))) or
                (contains(., 'd') and (contains(../anchor, 'm') or contains(../anchor, 'w') or contains(../anchor, 'd'))) or
                contains(., 'h')" {
                  error-message
                    "Certificate expiration notification period must be smaller than the anchor.";
                }

          description
            "The period of the notification. The period is the time
             between two notifications within the given time interval.";
        }
      }
    }

    leaf-list ignored-hello-module {
      type string;

      description
        "List of implemented sysrepo YANG modules that will not be reported the NETCONF server in its <hello> messages.";
    }
  }
}
