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(a)redhat.com>
---
docs/drivers.html.in | 1 +
docs/drvsecret.html.in | 82 ++++++++++++++++++++++++++++++++++++++
src/secret/secret_driver.c | 58 ++++++++++++++++++++++-----
3 files changed, 130 insertions(+), 11 deletions(-)
create mode 100644 docs/drvsecret.html.in
diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index 8743301ebd..34f98f60b6 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 a31005c731..210a16c3d3 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 */
+ char *embeddedRoot; /* 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;
@@ -475,7 +471,11 @@ secretStateInitialize(bool privileged,
driver->secretEventState = virObjectEventStateNew();
driver->privileged = privileged;
- if (privileged) {
+ if (root) {
+ driver->embeddedRoot = g_strdup(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 {
@@ -550,19 +550,54 @@ secretConnectOpen(virConnectPtr conn,
return VIR_DRV_OPEN_ERROR;
}
- if (!virConnectValidateURIPath(conn->uri->path,
- "secret",
- driver->privileged))
- return VIR_DRV_OPEN_ERROR;
+ if (driver->embeddedRoot) {
+ const char *root = virURIGetParam(conn->uri, "root");
+ if (!root)
+ return VIR_DRV_OPEN_ERROR;
+
+ if (STRNEQ(conn->uri->path, "/embed")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("URI must be secret:///embed"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ if (STRNEQ(root, driver->embeddedRoot)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot open embedded driver at path '%s',
"
+ "already open with path '%s'"),
+ root, driver->embeddedRoot);
+ 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->embeddedRoot) {
+ 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->embeddedRoot) {
+ secretDriverLock();
+ driver->embeddedRefs--;
+ if (driver->embeddedRefs == 0)
+ virSetConnectSecret(NULL);
+ secretDriverUnlock();
+ }
return 0;
}
@@ -655,6 +690,7 @@ static virHypervisorDriver secretHypervisorDriver = {
static virConnectDriver secretConnectDriver = {
.localOnly = true,
.uriSchemes = (const char *[]){ "secret", NULL },
+ .embeddable = true,
.hypervisorDriver = &secretHypervisorDriver,
.secretDriver = &secretDriver,
};
--
2.23.0