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@xxxxxxxxxx> --- 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@xxxxxxxxxxx/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 e0a55e51ca..72ee8ea44d 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 { @@ -550,19 +550,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; } @@ -655,6 +678,7 @@ static virHypervisorDriver secretHypervisorDriver = { static virConnectDriver secretConnectDriver = { .localOnly = true, .uriSchemes = (const char *[]){ "secret", NULL }, + .embeddable = true, .hypervisorDriver = &secretHypervisorDriver, .secretDriver = &secretDriver, }; -- 2.23.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list