[libvirt] [PATCH 6/7] secrets: add support for running secret driver in embedded mode

Daniel P. Berrangé berrange at redhat.com
Mon Dec 2 15:03:30 UTC 2019


This enables support for running the secret driver embedded to the
calling application process using a URI:

   secret:///embed?root=/some/path

When using the embedded mode with a root=/var/tmp/embed, the
driver will use the following paths:

       configDir: /var/tmp/embed/etc/secrets
        stateDir: /var/tmp/embed/run/secrets

These are identical whether the embedded driver is privileged
or unprivileged.

This compares with the system instance which uses

       configDir: /etc/libvirt/secrets
        stateDir: /var/lib/libvirt/secrets

When an embedded instance of the secret driver is open, any other
embedded drivers will automatically use the embedded secret driver.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 docs/drivers.html.in       |  1 +
 docs/drvsecret.html.in     | 82 ++++++++++++++++++++++++++++++++++++++
 src/secret/secret_driver.c | 46 ++++++++++++++++-----
 3 files changed, 118 insertions(+), 11 deletions(-)
 create mode 100644 docs/drvsecret.html.in

diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index 4539eedbcd..cb1ddc9212 100644
--- a/docs/drivers.html.in
+++ b/docs/drivers.html.in
@@ -8,6 +8,7 @@
       <li><a href="#hypervisor">Hypervisor drivers</a></li>
       <li><a href="storage.html">Storage drivers</a></li>
       <li><a href="drvnodedev.html">Node device driver</a></li>
+      <li><a href="drvsecret.html">Secret driver</a></li>
     </ul>
 
     <p>
diff --git a/docs/drvsecret.html.in b/docs/drvsecret.html.in
new file mode 100644
index 0000000000..9a05fe1f09
--- /dev/null
+++ b/docs/drvsecret.html.in
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <body>
+    <h1>Secret information management</h1>
+
+    <p>
+      The secrets driver in libvirt provides a simple interface for
+      storing and retrieving secret information.
+    </p>
+
+        <h2><a id="uris">Connections to SECRET driver</a></h2>
+
+    <p>
+    The libvirt SECRET driver is a multi-instance driver, providing a single
+    system wide privileged driver (the "system" instance), and per-user
+    unprivileged drivers (the "session" instance). A connection to the secret
+    driver is automatically available when opening a connection to one of the
+    stateful primary hypervisor drivers. It is none the less also possible to
+    explicitly open just the secret driver, using the URI protocol "secret"
+    Some example connection URIs for the driver are:
+    </p>
+
+<pre>
+secret:///session                      (local access to per-user instance)
+secret+unix:///session                 (local access to per-user instance)
+
+secret:///system                       (local access to system instance)
+secret+unix:///system                  (local access to system instance)
+secret://example.com/system            (remote access, TLS/x509)
+secret+tcp://example.com/system        (remote access, SASl/Kerberos)
+secret+ssh://root@example.com/system   (remote access, SSH tunnelled)
+</pre>
+
+    <h3><a id="uriembedded">Embedded driver</a></h3>
+
+    <p>
+      Since 6.0.0 the secret driver has experimental support for operating
+      in an embedded mode. In this scenario, rather than connecting to
+      the libvirtd daemon, the secret driver runs in the client application
+      process directly. To open the driver in embedded mode the app use the
+      new URI path and specify a virtual root directory under which the
+      driver will create content.
+    </p>
+
+    <pre>
+      secret:///embed?root=/some/dir
+    </pre>
+
+    <p>
+      Under the specified root directory the following locations will
+      be used
+    </p>
+
+    <pre>
+/some/dir
+  |
+  +- etc
+  |   |
+  |   +- secrets
+  |
+  +- run
+      |
+      +- secrets
+    </pre>
+
+    <p>
+      The application is responsible for recursively purging the contents
+      of this directory tree once they no longer require a connection,
+      though it can also be left intact for reuse when opening a future
+      connection.
+    </p>
+
+    <p>
+      The range of functionality is intended to be on a par with that
+      seen when using the traditional system or session libvirt connections
+      to QEMU. Normal practice would be to open the secret driver in embedded
+      mode any time one of the other drivers is opened in embedded mode so
+      that the two drivers can interact in-process.
+    </p>
+  </body>
+</html>
diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index d248121327..c791bde2f9 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -55,6 +55,8 @@ typedef virSecretDriverState *virSecretDriverStatePtr;
 struct _virSecretDriverState {
     virMutex lock;
     bool privileged; /* readonly */
+    bool embedded; /* readonly */
+    int embeddedRefs;
     virSecretObjListPtr secrets;
     char *stateDir;
     char *configDir;
@@ -456,12 +458,6 @@ secretStateInitialize(bool privileged,
                       virStateInhibitCallback callback G_GNUC_UNUSED,
                       void *opaque G_GNUC_UNUSED)
 {
-    if (root != NULL) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("Driver does not support embedded mode"));
-        return -1;
-    }
-
     if (VIR_ALLOC(driver) < 0)
         return VIR_DRV_STATE_INIT_ERROR;
 
@@ -474,8 +470,12 @@ secretStateInitialize(bool privileged,
 
     driver->secretEventState = virObjectEventStateNew();
     driver->privileged = privileged;
+    driver->embedded = root != NULL;
 
-    if (privileged) {
+    if (root) {
+        driver->configDir = g_strdup_printf("%s/etc/secrets", root);
+        driver->stateDir = g_strdup_printf("%s/run/secrets", root);
+    } else if (privileged) {
         driver->configDir = g_strdup_printf("%s/libvirt/secrets", SYSCONFDIR);
         driver->stateDir = g_strdup_printf("%s/libvirt/secrets", RUNSTATEDIR);
     } else {
@@ -552,19 +552,42 @@ secretConnectOpen(virConnectPtr conn,
         return VIR_DRV_OPEN_ERROR;
     }
 
-    if (!virConnectValidateURIPath(conn->uri->path,
-                                   "secret",
-                                   driver->privileged))
-        return VIR_DRV_OPEN_ERROR;
+    if (driver->embedded) {
+        if (STRNEQ(conn->uri->path, "/embed")) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("URI must be secret:///embed"));
+            return VIR_DRV_OPEN_ERROR;
+        }
+    } else {
+        if (!virConnectValidateURIPath(conn->uri->path,
+                                       "secret",
+                                       driver->privileged))
+            return VIR_DRV_OPEN_ERROR;
+    }
 
     if (virConnectOpenEnsureACL(conn) < 0)
         return VIR_DRV_OPEN_ERROR;
 
+    if (driver->embedded) {
+        secretDriverLock();
+        if (driver->embeddedRefs == 0)
+            virSetConnectSecret(conn);
+        driver->embeddedRefs++;
+        secretDriverUnlock();
+    }
+
     return VIR_DRV_OPEN_SUCCESS;
 }
 
 static int secretConnectClose(virConnectPtr conn G_GNUC_UNUSED)
 {
+    if (driver->embedded) {
+        secretDriverLock();
+        driver->embeddedRefs--;
+        if (driver->embeddedRefs == 0)
+            virSetConnectSecret(NULL);
+        secretDriverUnlock();
+    }
     return 0;
 }
 
@@ -657,6 +680,7 @@ static virHypervisorDriver secretHypervisorDriver = {
 static virConnectDriver secretConnectDriver = {
     .localOnly = true,
     .uriSchemes = (const char *[]){ "secret", NULL },
+    .embeddable = true,
     .hypervisorDriver = &secretHypervisorDriver,
     .secretDriver = &secretDriver,
 };
-- 
2.23.0




More information about the libvir-list mailing list