mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
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:
parent
068efae5b1
commit
3e9076e777
@ -8,6 +8,7 @@
|
|||||||
<li><a href="#hypervisor">Hypervisor drivers</a></li>
|
<li><a href="#hypervisor">Hypervisor drivers</a></li>
|
||||||
<li><a href="storage.html">Storage 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="drvnodedev.html">Node device driver</a></li>
|
||||||
|
<li><a href="drvsecret.html">Secret driver</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
82
docs/drvsecret.html.in
Normal file
82
docs/drvsecret.html.in
Normal 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>
|
@ -55,6 +55,8 @@ typedef virSecretDriverState *virSecretDriverStatePtr;
|
|||||||
struct _virSecretDriverState {
|
struct _virSecretDriverState {
|
||||||
virMutex lock;
|
virMutex lock;
|
||||||
bool privileged; /* readonly */
|
bool privileged; /* readonly */
|
||||||
|
char *embeddedRoot; /* readonly */
|
||||||
|
int embeddedRefs;
|
||||||
virSecretObjListPtr secrets;
|
virSecretObjListPtr secrets;
|
||||||
char *stateDir;
|
char *stateDir;
|
||||||
char *configDir;
|
char *configDir;
|
||||||
@ -456,12 +458,6 @@ secretStateInitialize(bool privileged,
|
|||||||
virStateInhibitCallback callback G_GNUC_UNUSED,
|
virStateInhibitCallback callback G_GNUC_UNUSED,
|
||||||
void *opaque 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)
|
if (VIR_ALLOC(driver) < 0)
|
||||||
return VIR_DRV_STATE_INIT_ERROR;
|
return VIR_DRV_STATE_INIT_ERROR;
|
||||||
|
|
||||||
@ -475,7 +471,11 @@ secretStateInitialize(bool privileged,
|
|||||||
driver->secretEventState = virObjectEventStateNew();
|
driver->secretEventState = virObjectEventStateNew();
|
||||||
driver->privileged = privileged;
|
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->configDir = g_strdup_printf("%s/libvirt/secrets", SYSCONFDIR);
|
||||||
driver->stateDir = g_strdup_printf("%s/libvirt/secrets", RUNSTATEDIR);
|
driver->stateDir = g_strdup_printf("%s/libvirt/secrets", RUNSTATEDIR);
|
||||||
} else {
|
} else {
|
||||||
@ -550,19 +550,54 @@ secretConnectOpen(virConnectPtr conn,
|
|||||||
return VIR_DRV_OPEN_ERROR;
|
return VIR_DRV_OPEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!virConnectValidateURIPath(conn->uri->path,
|
if (driver->embeddedRoot) {
|
||||||
"secret",
|
const char *root = virURIGetParam(conn->uri, "root");
|
||||||
driver->privileged))
|
if (!root)
|
||||||
return VIR_DRV_OPEN_ERROR;
|
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)
|
if (virConnectOpenEnsureACL(conn) < 0)
|
||||||
return VIR_DRV_OPEN_ERROR;
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
|
||||||
|
if (driver->embeddedRoot) {
|
||||||
|
secretDriverLock();
|
||||||
|
if (driver->embeddedRefs == 0)
|
||||||
|
virSetConnectSecret(conn);
|
||||||
|
driver->embeddedRefs++;
|
||||||
|
secretDriverUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
return VIR_DRV_OPEN_SUCCESS;
|
return VIR_DRV_OPEN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secretConnectClose(virConnectPtr conn G_GNUC_UNUSED)
|
static int secretConnectClose(virConnectPtr conn G_GNUC_UNUSED)
|
||||||
{
|
{
|
||||||
|
if (driver->embeddedRoot) {
|
||||||
|
secretDriverLock();
|
||||||
|
driver->embeddedRefs--;
|
||||||
|
if (driver->embeddedRefs == 0)
|
||||||
|
virSetConnectSecret(NULL);
|
||||||
|
secretDriverUnlock();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,6 +690,7 @@ static virHypervisorDriver secretHypervisorDriver = {
|
|||||||
static virConnectDriver secretConnectDriver = {
|
static virConnectDriver secretConnectDriver = {
|
||||||
.localOnly = true,
|
.localOnly = true,
|
||||||
.uriSchemes = (const char *[]){ "secret", NULL },
|
.uriSchemes = (const char *[]){ "secret", NULL },
|
||||||
|
.embeddable = true,
|
||||||
.hypervisorDriver = &secretHypervisorDriver,
|
.hypervisorDriver = &secretHypervisorDriver,
|
||||||
.secretDriver = &secretDriver,
|
.secretDriver = &secretDriver,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user