Subject: [netconf] client identification in ietf-netconf-server

From: Martin Bjorklund <[email-masked]>
Date: Wed, 30 Oct 2019 15:55:54 +0100 (CET)

Hi,

The ietf-netconf-server module has this:

  grouping netconf-server-grouping {
    ...
    container client-identification {
      ...
      container cert-maps {
        when "../../../../tls";
        uses x509c2n:cert-to-name;
        ...
      }
    }
  }

Note the "when" expression.  This means that the grouping has a strong
depency on where is it used.  We should try to avoid such a design.

But should't this cert-to-name list be available when x509-certs are
used also with SSH?  The current data model for ssh specifies certs on
a per-user basis. But this requires lots of configuration in the case
that the cert encodes the user name (even though the name is in the
cert you have to configure each user on each device).  I suggest we
align the model for SSH with the TLS model for cert identification.

For TLS, the data model has the following structure:

  +--rw netconf-server
     +--rw listen! {ssh-listen or tls-listen}?
        +--rw idle-timeout?   uint16
        +--rw endpoint* [name]
           +--rw name         string
           +--rw (transport)
              ...
              +--:(tls) {tls-listen}?

    [ reset indentation to make the diagram easier to read ]

   +--rw tls
      +--rw tcp-server-parameters
      ...
      +--rw tls-server-parameters
      |  +--rw server-identity
            ...
      |  +--rw client-authentication!
      |  |  +--rw (required-or-optional)
      |  |  |  +--:(required)
      |  |  |  |  +--rw required?    empty
      |  |  |  +--:(optional)
      |  |  |     +--rw optional?    empty
      |  |  +--rw (local-or-external)
      |  |     +--:(local)  {local-client-auth-supported}?
      |  |     |  +--rw ca-certs!   {ts:x509-certificates}?
      |  |     |  |  +--rw (local-or-truststore)
      |  |     |  |     +--:(local)  {local-definitions-supported}?
      |  |     |  |     |  +--rw local-definition
      |  |     |  |     |     +--rw cert*   trust-anchor-cert-cms
      |  |     |  |     |     +---n certificate-expiration
      |  |     |  |     |        +-- expiration-date
      |  |     |  |     |                yang:date-and-time
      |  |     |  |     +--:(truststore)
      |  |     |  |              {truststore-supported,x509-certificates}?
      |  |     |  |        +--rw truststore-reference?
      |  |     |  |                ts:certificates-ref
      |  |     |  +--rw client-certs!  {ts:x509-certificates}?
      |  |     |     +--rw (local-or-truststore)
      |  |     |        +--:(local)  {local-definitions-supported}?
      |  |     |        |  +--rw local-definition
      |  |     |        |     +--rw cert*     trust-anchor-cert-cms
      |  |     |        |     +---n certificate-expiration
      |  |     |        |        +-- expiration-date
      |  |     |        |                yang:date-and-time
      |  |     |        +--:(truststore)
      |  |     |                 {truststore-supported,x509-certificates}?
      |  |     |           +--rw truststore-reference?
      |  |     |                   ts:certificates-ref
      |  |     +--:(external)
      |  |              {external-client-auth-supported}?
      |  |        +--rw client-auth-defined-elsewhere?
      |  |                empty
          ...
      +--rw netconf-server-parameters
         +--rw client-identification
            +--rw cert-maps
               +--rw cert-to-name* [id]
                  +--rw id             uint32
                  +--rw fingerprint
                  |       x509c2n:tls-fingerprint
                  +--rw map-type       identityref
                  +--rw name           string

It is not clear how this is used by the server to end up either with
an authenticated user name or failed authentication.

First of all, how is the "required-or-optional" choice used in a
NETCONF server?  What happens if an operation configures this to
"optional"?  (side note: why is this a choice of empty leafs instead
of a leaf?)

Second, I assume that the idea is that the server uses the config
params in "local-or-external" and the certificate presented by the
client and after this step is either accepted or rejected.  It is not
clear what is supposed to happen if someone configures
"client-auth-defined-elsewhere".  I think it is better to not define
this case, but (perhaps) keep the choice and explain that other
modules can augment additional config params here for other
authentication mechanisms.

Next, my guess is that the intention is that if the cert was accepted
in the step above, it is checked in cert-to-name to see if a user name
can be derived.

In another thread you mentioned that if a local cert is configured, it
seems redundant to also configure the cert as a fingerprint in
cert-to-name.  I'm not sure about this.  But perhaps you can use the
same "map-type" and "name" leafs in the "client-cert" container?  It
is not as easy for the "truststore-reference"; perhaps you'd have to
augment the truststore with these leafs in this case.

/martin