secrets: add support for running secret driver in embedded mode

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.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-05-17 12:35:57 +01:00
parent 068efae5b1
commit 3e9076e777
3 changed files with 130 additions and 11 deletions

View File

@ -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>

82
docs/drvsecret.html.in Normal file
View File

@ -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>

View File

@ -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,
};