Add {keystore,truststore}-api and none implementations 05/102205/41
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 22 Aug 2022 13:08:15 +0000 (15:08 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 20 Oct 2022 15:02:22 +0000 (17:02 +0200)
The configuration bits for NETCONF/RESTCONF clients and server are part
of a large scale effort in NETCONF WG. In particular the concept of
crypto types and a keystore/truststore are shared between SSH and TLS
transports.

This patch adds the YANG models and an a 'none' implementation, which
the central keystore/truststore.

JIRA: NETCONF-590
Change-Id: I0827756df83aa9cfc83e98ee50b1e44f6310e82e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
12 files changed:
artifacts/pom.xml
keystore/keystore-api/pom.xml [new file with mode: 0644]
keystore/keystore-api/src/main/yang/ietf-keystore@2022-05-24.yang [new file with mode: 0644]
keystore/keystore-none/pom.xml [new file with mode: 0644]
keystore/keystore-none/src/main/java/org/opendaylight/netconf/keystore/none/NoneKeystoreFeatureProvider.java [new file with mode: 0644]
keystore/pom.xml [new file with mode: 0644]
pom.xml
truststore/pom.xml [new file with mode: 0644]
truststore/truststore-api/pom.xml [new file with mode: 0644]
truststore/truststore-api/src/main/yang/ietf-truststore@2022-05-24.yang [new file with mode: 0644]
truststore/truststore-none/pom.xml [new file with mode: 0644]
truststore/truststore-none/src/main/java/org/opendaylight/netconf/truststore/none/NoneTruststoreFeatureProvider.java [new file with mode: 0644]

index 9d4c4f0985a5a92bb6803f86a208ea9965c3c52c..6a8a7d00abc593c6767dee67577340cd98da263e 100644 (file)
                 <scope>test</scope>
             </dependency>
 
+            <!-- Keystore API and implementations. This is a manifestation of draft-ietf-netconf-keystore. -->
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>keystore-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>keystore-none</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <!-- Truststore API and implementations. This is a manifestation of draft-ietf-netconf-truststore. -->
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>truststore-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>truststore-none</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.opendaylight.netconf</groupId>
                 <artifactId>yanglib</artifactId>
diff --git a/keystore/keystore-api/pom.xml b/keystore/keystore-api/pom.xml
new file mode 100644 (file)
index 0000000..11fd376
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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>4.0.3-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>keystore-api</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf.model</groupId>
+            <artifactId>draft-ietf-netconf-crypto-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf.model</groupId>
+            <artifactId>rfc8341</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/keystore/keystore-api/src/main/yang/ietf-keystore@2022-05-24.yang b/keystore/keystore-api/src/main/yang/ietf-keystore@2022-05-24.yang
new file mode 100644 (file)
index 0000000..345e0aa
--- /dev/null
@@ -0,0 +1,412 @@
+module ietf-keystore {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-keystore";
+  prefix ks;
+
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+
+  import ietf-crypto-types {
+    prefix ct;
+    reference
+      "RFC AAAA: YANG Data Types and Groupings for Cryptography";
+  }
+
+  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 defines a 'keystore' to centralize management
+     of security credentials.
+
+     Copyright (c) 2022 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 CCCC
+     (https://www.rfc-editor.org/info/rfcCCCC); 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 2022-05-24 {
+    description
+      "Initial version";
+    reference
+      "RFC CCCC: A YANG Data Model for a Keystore";
+  }
+
+  /****************/
+  /*   Features   */
+  /****************/
+
+  feature central-keystore-supported {
+    description
+      "The 'central-keystore-supported' feature indicates that
+       the server supports the keystore (i.e., implements the
+       'ietf-keystore' module).";
+  }
+
+  feature local-definitions-supported {
+    description
+      "The 'local-definitions-supported' feature indicates that
+       the server supports locally-defined keys.";
+  }
+
+  feature asymmetric-keys {
+    description
+      "The 'asymmetric-keys' feature indicates that the server
+       supports asymmetric keys in keystores.";
+  }
+
+  feature symmetric-keys {
+    description
+      "The 'symmetric-keys' feature indicates that the server
+       supports symmetric keys in keystores.";
+  }
+
+  /****************/
+  /*   Typedefs   */
+  /****************/
+
+  typedef symmetric-key-ref {
+    type leafref {
+      path "/ks:keystore/ks:symmetric-keys/ks:symmetric-key"
+         + "/ks:name";
+    }
+    description
+      "This typedef enables modules to easily define a reference
+       to a symmetric key stored in the keystore, when this
+       module is implemented.";
+  }
+
+  typedef asymmetric-key-ref {
+    type leafref {
+      path "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key"
+         + "/ks:name";
+    }
+    description
+      "This typedef enables modules to easily define a reference
+       to an asymmetric key stored in the keystore, when this
+       module is implemented.";
+  }
+
+  /*****************/
+  /*   Groupings   */
+  /*****************/
+
+  grouping encrypted-by-choice-grouping {
+    description
+      "A grouping that defines a 'choice' statement that can be
+       augmented into the 'encrypted-by' node, present in the
+       'symmetric-key-grouping' and 'asymmetric-key-pair-grouping'
+       groupings defined in RFC AAAA, enabling references to keys
+       in the keystore, when this module is implemented.";
+    choice encrypted-by-choice {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice amongst other symmetric or asymmetric keys.";
+      case symmetric-key-ref {
+        if-feature "central-keystore-supported";
+        if-feature "symmetric-keys";
+        leaf symmetric-key-ref {
+          type ks:symmetric-key-ref;
+          description
+            "Identifies the symmetric key used to encrypt the
+             associated key.";
+        }
+      }
+      case asymmetric-key-ref {
+        if-feature "central-keystore-supported";
+        if-feature "asymmetric-keys";
+        leaf asymmetric-key-ref {
+          type ks:asymmetric-key-ref;
+          description
+            "Identifies the asymmetric key whose public key
+             encrypted the associated key.";
+        }
+      }
+    }
+  }
+
+  grouping asymmetric-key-certificate-ref-grouping {
+    description
+      "This grouping defines a reference to a specific certificate
+       associated with an asymmetric key stored in the keystore,
+       when this module is implemented.";
+    leaf asymmetric-key {
+      nacm:default-deny-write;
+      if-feature "central-keystore-supported";
+      if-feature "asymmetric-keys";
+      type ks:asymmetric-key-ref;
+      must '../certificate';
+      description
+        "A reference to an asymmetric key in the keystore.";
+    }
+    leaf certificate {
+      nacm:default-deny-write;
+      type leafref {
+        path "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key"
+           + "[ks:name = current()/../asymmetric-key]/"
+           + "ks:certificates/ks:certificate/ks:name";
+      }
+      must '../asymmetric-key';
+      description
+        "A reference to a specific certificate of the
+         asymmetric key in the keystore.";
+    }
+  }
+
+  // local-or-keystore-* groupings
+
+  grouping local-or-keystore-symmetric-key-grouping {
+    description
+      "A grouping that expands to allow the symmetric key to be
+       either stored locally, i.e., within the using data model,
+       or a reference to a symmetric key stored in the keystore.
+
+       Servers that do not 'implement' this module, and hence
+       'central-keystore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate keystore locations.";
+    choice local-or-keystore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the keystore.";
+      case local {
+        if-feature "local-definitions-supported";
+        if-feature "symmetric-keys";
+        container local-definition {
+          description
+            "Container to hold the local key definition.";
+          uses ct:symmetric-key-grouping;
+        }
+      }
+      case keystore {
+        if-feature "central-keystore-supported";
+        if-feature "symmetric-keys";
+        leaf keystore-reference {
+          type ks:symmetric-key-ref;
+          description
+            "A reference to an symmetric key that exists in
+             the keystore, when this module is implemented.";
+        }
+      }
+    }
+  }
+  grouping local-or-keystore-asymmetric-key-grouping {
+    description
+      "A grouping that expands to allow the asymmetric key to be
+       either stored locally, i.e., within the using data model,
+       or a reference to an asymmetric key stored in the keystore.
+
+       Servers that do not 'implement' this module, and hence
+       'central-keystore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate keystore locations.";
+    choice local-or-keystore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the keystore.";
+      case local {
+        if-feature "local-definitions-supported";
+        if-feature "asymmetric-keys";
+        container local-definition {
+          description
+            "Container to hold the local key definition.";
+          uses ct:asymmetric-key-pair-grouping;
+        }
+      }
+      case keystore {
+        if-feature "central-keystore-supported";
+        if-feature "asymmetric-keys";
+        leaf keystore-reference {
+          type ks:asymmetric-key-ref;
+          description
+            "A reference to an asymmetric key that exists in
+             the keystore, when this module is implemented.  The
+             intent is to reference just the asymmetric key
+             without any regard for any certificates that may
+             be associated with it.";
+        }
+      }
+    }
+  }
+
+  grouping local-or-keystore-asymmetric-key-with-certs-grouping {
+    description
+      "A grouping that expands to allow an asymmetric key and
+       its associated certificates to be either stored locally,
+       i.e., within the using data model, or a reference to an
+       asymmetric key (and its associated certificates) stored
+       in the keystore.
+       Servers that do not 'implement' this module, and hence
+       'central-keystore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate keystore locations.";
+    choice local-or-keystore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the keystore.";
+      case local {
+        if-feature "local-definitions-supported";
+        if-feature "asymmetric-keys";
+        container local-definition {
+          description
+            "Container to hold the local key definition.";
+          uses ct:asymmetric-key-pair-with-certs-grouping;
+        }
+      }
+      case keystore {
+        if-feature "central-keystore-supported";
+        if-feature "asymmetric-keys";
+        leaf keystore-reference {
+          type ks:asymmetric-key-ref;
+          description
+            "A reference to an asymmetric-key (and all of its
+             associated certificates) in the keystore, when
+             this module is implemented.";
+        }
+      }
+    }
+  }
+
+  grouping local-or-keystore-end-entity-cert-with-key-grouping {
+    description
+      "A grouping that expands to allow an end-entity certificate
+       (and its associated asymmetric key pair) to be either stored
+       locally, i.e., within the using data model, or a reference
+       to a specific certificate in the keystore.
+
+       Servers that do not 'implement' this module, and hence
+       'central-keystore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate keystore locations.";
+    choice local-or-keystore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the keystore.";
+      case local {
+        if-feature "local-definitions-supported";
+        if-feature "asymmetric-keys";
+        container local-definition {
+          description
+            "Container to hold the local key definition.";
+          uses ct:asymmetric-key-pair-with-cert-grouping;
+        }
+      }
+      case keystore {
+        if-feature "central-keystore-supported";
+        if-feature "asymmetric-keys";
+        container keystore-reference {
+          uses asymmetric-key-certificate-ref-grouping;
+          description
+            "A reference to a specific certificate associated with
+             an asymmetric key stored in the keystore, when this
+             module is implemented.";
+        }
+      }
+    }
+  }
+
+  grouping keystore-grouping {
+    description
+      "Grouping definition enables use in other contexts.  If ever
+       done, implementations MUST augment new 'case' statements
+       into the various local-or-keystore 'choice' statements to
+       supply leafrefs to the model-specific location(s).";
+    container asymmetric-keys {
+      nacm:default-deny-write;
+      if-feature "asymmetric-keys";
+      description
+        "A list of asymmetric keys.";
+      list asymmetric-key {
+        key "name";
+        description
+          "An asymmetric key.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the asymmetric key.";
+        }
+        uses ct:asymmetric-key-pair-with-certs-grouping;
+      }
+    }
+    container symmetric-keys {
+      nacm:default-deny-write;
+      if-feature "symmetric-keys";
+      description
+        "A list of symmetric keys.";
+      list symmetric-key {
+        key "name";
+        description
+          "A symmetric key.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the symmetric key.";
+        }
+        uses ct:symmetric-key-grouping;
+      }
+    }
+  }
+
+  /*********************************/
+  /*   Protocol accessible nodes   */
+  /*********************************/
+
+  container keystore {
+    if-feature central-keystore-supported;
+    description
+      "A central keystore containing a list of symmetric keys and
+       a list of asymmetric keys.";
+    nacm:default-deny-write;
+    uses keystore-grouping {
+      augment "symmetric-keys/symmetric-key/key-type/encrypted-key/"
+            + "encrypted-key/encrypted-by" {
+        description
+          "Augments in a choice statement enabling the encrypting
+           key to be any other symmetric or asymmetric key in the
+           central keystore.";
+        uses encrypted-by-choice-grouping;
+      }
+      augment "asymmetric-keys/asymmetric-key/private-key-type/"
+            + "encrypted-private-key/encrypted-private-key/"
+            + "encrypted-by" {
+        description
+          "Augments in a choice statement enabling the encrypting
+           key to be any other symmetric or asymmetric key in the
+           central keystore.";
+        uses encrypted-by-choice-grouping;
+      }
+    }
+  }
+}
diff --git a/keystore/keystore-none/pom.xml b/keystore/keystore-none/pom.xml
new file mode 100644 (file)
index 0000000..abd7b80
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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>4.0.3-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>keystore-none</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.kohsuke.metainf-services</groupId>
+            <artifactId>metainf-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>keystore-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/keystore/keystore-none/src/main/java/org/opendaylight/netconf/keystore/none/NoneKeystoreFeatureProvider.java b/keystore/keystore-none/src/main/java/org/opendaylight/netconf/keystore/none/NoneKeystoreFeatureProvider.java
new file mode 100644 (file)
index 0000000..a526124
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 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.netconf.keystore.none;
+
+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.keystore.rev220524.AsymmetricKeys;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.keystore.rev220524.IetfKeystoreData;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.keystore.rev220524.LocalDefinitionsSupported;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Simple implementation, which advertizes we do not have a central keystore and support asymmetric keys only.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class NoneKeystoreFeatureProvider implements YangFeatureProvider<IetfKeystoreData> {
+    @Override
+    public Class<IetfKeystoreData> boundModule() {
+        return IetfKeystoreData.class;
+    }
+
+    @Override
+    public Set<? extends YangFeature<?, IetfKeystoreData>> supportedFeatures() {
+        return Set.of(LocalDefinitionsSupported.VALUE, AsymmetricKeys.VALUE);
+    }
+}
diff --git a/keystore/pom.xml b/keystore/pom.xml
new file mode 100644 (file)
index 0000000..55a567a
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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.odlparent</groupId>
+        <artifactId>odlparent-lite</artifactId>
+        <version>11.0.1</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.netconf</groupId>
+    <artifactId>keystore-aggregator</artifactId>
+    <version>4.0.3-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+
+    <properties>
+        <maven.deploy.skip>true</maven.deploy.skip>
+        <maven.install.skip>true</maven.install.skip>
+    </properties>
+
+    <modules>
+        <module>keystore-api</module>
+        <module>keystore-none</module>
+    </modules>
+</project>
diff --git a/pom.xml b/pom.xml
index 99e3e0779f74daedfe5c7674836b95003ccec799..0b833a48d36290bc7c6ec0597c71512a2cd47055 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,9 @@
         <!-- Legacy layout -->
         <module>netconf</module>
         <module>restconf</module>
+
+        <module>keystore</module>
+        <module>truststore</module>
     </modules>
 
     <profiles>
diff --git a/truststore/pom.xml b/truststore/pom.xml
new file mode 100644 (file)
index 0000000..a7a33c7
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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.odlparent</groupId>
+        <artifactId>odlparent-lite</artifactId>
+        <version>11.0.1</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.netconf</groupId>
+    <artifactId>truststore-aggregator</artifactId>
+    <version>4.0.3-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+
+    <properties>
+        <maven.deploy.skip>true</maven.deploy.skip>
+        <maven.install.skip>true</maven.install.skip>
+    </properties>
+
+    <modules>
+        <module>truststore-api</module>
+        <module>truststore-none</module>
+    </modules>
+</project>
diff --git a/truststore/truststore-api/pom.xml b/truststore/truststore-api/pom.xml
new file mode 100644 (file)
index 0000000..0b451f4
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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>4.0.3-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>truststore-api</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf.model</groupId>
+            <artifactId>draft-ietf-netconf-crypto-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf.model</groupId>
+            <artifactId>rfc8341</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/truststore/truststore-api/src/main/yang/ietf-truststore@2022-05-24.yang b/truststore/truststore-api/src/main/yang/ietf-truststore@2022-05-24.yang
new file mode 100644 (file)
index 0000000..7aaf7a2
--- /dev/null
@@ -0,0 +1,339 @@
+module ietf-truststore {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-truststore";
+  prefix ts;
+
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+
+  import ietf-crypto-types {
+    prefix ct;
+    reference
+      "RFC AAAA: YANG Data Types and Groupings for Cryptography";
+  }
+
+  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 <kent+ietf@watsen.net>";
+  description
+    "This module defines a 'truststore' to centralize management
+     of trust anchors including certificates and public keys.
+
+     Copyright (c) 2021 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 BBBB
+     (https://www.rfc-editor.org/info/rfcBBBB); 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 2022-05-24 {
+    description
+      "Initial version";
+    reference
+      "RFC BBBB: A YANG Data Model for a Truststore";
+  }
+
+  /****************/
+  /*   Features   */
+  /****************/
+
+  feature central-truststore-supported {
+    description
+      "The 'central-truststore-supported' feature indicates that
+       the server supports the truststore (i.e., implements the
+       'ietf-truststore' module).";
+  }
+
+  feature local-definitions-supported {
+    description
+      "The 'local-definitions-supported' feature indicates that
+       the server supports locally-defined trust anchors.";
+  }
+  feature certificates {
+    description
+      "The 'certificates' feature indicates that the server
+       implements the /truststore/certificate-bags subtree.";
+  }
+
+  feature public-keys {
+    description
+      "The 'public-keys' feature indicates that the server
+       implements the /truststore/public-key-bags subtree.";
+  }
+
+  /****************/
+  /*   Typedefs   */
+  /****************/
+
+  typedef certificate-bag-ref {
+    type leafref {
+      path "/ts:truststore/ts:certificate-bags/"
+         + "ts:certificate-bag/ts:name";
+    }
+    description
+      "This typedef defines a reference to a certificate bag
+       in the truststore, when this module is implemented.";
+  }
+
+  typedef certificate-ref {
+    type leafref {
+      path "/ts:truststore/ts:certificate-bags/ts:certificate-bag"
+         + "[ts:name = current()/../ts:certificate-bag]/"
+         + "ts:certificate/ts:name";
+    }
+    description
+      "This typedef defines a reference to a specific certificate
+       in a certificate bag in the truststore, when this module
+       is implemented.  This typedef requires that there exist a
+       sibling 'leaf' node called 'certificate-bag' that SHOULD
+       have the typedef 'certificate-bag-ref'.";
+  }
+
+  typedef public-key-bag-ref {
+    type leafref {
+      path "/ts:truststore/ts:public-key-bags/"
+         + "ts:public-key-bag/ts:name";
+    }
+    description
+      "This typedef defines a reference to a public key bag
+       in the truststore, when this module is implemented.";
+  }
+
+  typedef public-key-ref {
+    type leafref {
+      path "/ts:truststore/ts:public-key-bags/ts:public-key-bag"
+         + "[ts:name = current()/../ts:public-key-bag]/"
+         + "ts:public-key/ts:name";
+    }
+    description
+      "This typedef defines a reference to a specific public key
+       in a public key bag in the truststore, when this module is
+       implemented.  This typedef requires that there exist a
+       sibling 'leaf' node called 'public-key-bag' that SHOULD
+       have the typedef 'public-key-bag-ref'.";
+  }
+
+  /*****************/
+  /*   Groupings   */
+  /*****************/
+
+  grouping local-or-truststore-certs-grouping {
+    description
+      "A grouping that allows the certificates to be either
+       configured locally, within the using data model, or be a
+       reference to a certificate bag stored in the truststore.
+
+       Servers that do not 'implement' this module, and hence
+       'central-truststore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate truststore locations.";
+    choice local-or-truststore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the truststore.";
+      case local {
+        if-feature "local-definitions-supported";
+        container local-definition {
+          description
+            "A container for locally configured trust anchor
+             certificates.";
+          list certificate {
+            key "name";
+            min-elements 1;
+            description
+              "A trust anchor certificate.";
+            leaf name {
+              type string;
+              description
+                "An arbitrary name for this certificate.";
+            }
+            uses ct:trust-anchor-cert-grouping {
+              refine "cert-data" {
+                mandatory true;
+              }
+            }
+          }
+        }
+      }
+      case truststore {
+        if-feature "central-truststore-supported";
+        if-feature "certificates";
+        leaf truststore-reference {
+          type ts:certificate-bag-ref;
+          description
+            "A reference to a certificate bag that exists in the
+             truststore, when this module is implemented.";
+        }
+      }
+    }
+  }
+
+  grouping local-or-truststore-public-keys-grouping {
+    description
+      "A grouping that allows the public keys to be either
+       configured locally, within the using data model, or be a
+       reference to a public key bag stored in the truststore.
+
+       Servers that do not 'implement' this module, and hence
+       'central-truststore-supported' is not defined, SHOULD
+       augment in custom 'case' statements enabling references
+       to the alternate truststore locations.";
+    choice local-or-truststore {
+      nacm:default-deny-write;
+      mandatory true;
+      description
+        "A choice between an inlined definition and a definition
+         that exists in the truststore.";
+      case local {
+        if-feature "local-definitions-supported";
+        container local-definition {
+          description
+            "A container to hold local public key definitions.";
+          list public-key {
+            key "name";
+            description
+              "A public key definition.";
+            leaf name {
+              type string;
+              description
+                "An arbitrary name for this public key.";
+            }
+            uses ct:public-key-grouping;
+          }
+        }
+      }
+      case truststore {
+        if-feature "central-truststore-supported";
+        if-feature "public-keys";
+        leaf truststore-reference {
+          type ts:public-key-bag-ref;
+          description
+            "A reference to a bag of public keys that exists
+             in the truststore, when this module is implemented.";
+        }
+      }
+    }
+  }
+
+  grouping truststore-grouping {
+    description
+      "A grouping definition that enables use in other contexts.
+       Where used, implementations MUST augment new 'case'
+       statements into the various local-or-truststore 'choice'
+       statements to supply leafrefs to the model-specific
+       location(s).";
+    container certificate-bags {
+      nacm:default-deny-write;
+      if-feature "certificates";
+      description
+        "A collection of certificate bags.";
+      list certificate-bag {
+        key "name";
+        description
+          "A bag of certificates.  Each bag of certificates SHOULD
+           be for a specific purpose.  For instance, one bag could
+           be used to authenticate a specific set of servers, while
+           another could be used to authenticate a specific set of
+           clients.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for this bag of certificates.";
+        }
+        leaf description {
+          type string;
+          description
+            "A description for this bag of certificates.  The
+             intended purpose for the bag SHOULD be described.";
+        }
+        list certificate {
+          key "name";
+          description
+            "A trust anchor certificate.";
+          leaf name {
+            type string;
+            description
+              "An arbitrary name for this certificate.";
+          }
+          uses ct:trust-anchor-cert-grouping {
+            refine "cert-data" {
+              mandatory true;
+            }
+          }
+        }
+      }
+    }
+    container public-key-bags {
+      nacm:default-deny-write;
+      if-feature "public-keys";
+      description
+        "A collection of public key bags.";
+      list public-key-bag {
+        key "name";
+        description
+          "A bag of public keys.  Each bag of keys SHOULD be for
+           a specific purpose.  For instance, one bag could be used
+           authenticate a specific set of servers, while another
+           could be used to authenticate a specific set of clients.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for this bag of public keys.";
+        }
+        leaf description {
+          type string;
+          description
+            "A description for this bag public keys.  The
+             intended purpose for the bag SHOULD be described.";
+        }
+        list public-key {
+          key "name";
+          description
+            "A public key.";
+          leaf name {
+            type string;
+            description
+              "An arbitrary name for this public key.";
+          }
+          uses ct:public-key-grouping;
+        }
+      }
+    }
+  }
+
+  /*********************************/
+  /*   Protocol accessible nodes   */
+  /*********************************/
+
+  container truststore {
+    if-feature central-truststore-supported;
+    nacm:default-deny-write;
+    description
+      "The truststore contains bags of certificates and
+       public keys.";
+    uses truststore-grouping;
+  }
+}
diff --git a/truststore/truststore-none/pom.xml b/truststore/truststore-none/pom.xml
new file mode 100644 (file)
index 0000000..2e6f102
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2022 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>4.0.3-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>truststore-none</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.kohsuke.metainf-services</groupId>
+            <artifactId>metainf-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>truststore-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/truststore/truststore-none/src/main/java/org/opendaylight/netconf/truststore/none/NoneTruststoreFeatureProvider.java b/truststore/truststore-none/src/main/java/org/opendaylight/netconf/truststore/none/NoneTruststoreFeatureProvider.java
new file mode 100644 (file)
index 0000000..72b072a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 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.netconf.truststore.none;
+
+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.truststore.rev220524.IetfTruststoreData;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.truststore.rev220524.LocalDefinitionsSupported;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Simple implementation, which advertizes we do not have a central truststore.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class NoneTruststoreFeatureProvider implements YangFeatureProvider<IetfTruststoreData> {
+    @Override
+    public Class<IetfTruststoreData> boundModule() {
+        return IetfTruststoreData.class;
+    }
+
+    @Override
+    public Set<? extends YangFeature<?, IetfTruststoreData>> supportedFeatures() {
+        return Set.of(LocalDefinitionsSupported.VALUE);
+    }
+}