Add virsh commands for secrets APIs

* src/virsh.c: Add virsh commands.
* docs/virsh.pod, virsh.1: Update documentation.
This commit is contained in:
Miloslav Trmač 2009-07-28 12:27:25 +02:00 committed by Daniel P. Berrange
parent 03d338608d
commit 2db2c5a186
3 changed files with 399 additions and 1 deletions

View File

@ -543,6 +543,49 @@ Convert a network name to network UUID.
=back
=head1 SECRET COMMMANDS
The following commands manipulate "secrets" (e.g. passwords, passphrases and
encryption keys). Libvirt can store secrets independently from their use, and
other objects (e.g. volumes or domains) can refer to the secrets for encryption
or possibly other uses. Secrets are identified using an UUID. See
L<http://libvirt.org/formatsecret.html> for documentation of the XML format
used to represent properties of secrets.
=over 4
=item B<secret-define> I<file>
Create a secret with the properties specified in I<file>, with no associated
secret value. If I<file> does not specify a UUID, choose one automatically.
If I<file> specifies an UUID of an existing secret, replace its properties by
properties defined in I<file>, without affecting the secret value.
=item B<secret-dumpxml> I<secret>
Output properties of I<secret> (specified by its UUID) as an XML dump to stdout.
=item B<secret-set-value> I<secret> I<base64>
Set the value associated with I<secret> (specified by its UUID) to the value
Base64-encoded value I<base64>.
=item B<secret-get-value> I<secret>
Output the value associated with I<secret> (specified by its UUID) to stdout,
encoded using Base64.
=item B<secret-undefine> I<secret>
Delete a I<secret> (specified by its UUID), including the associated value, if
any.
=item B<secret-list>
Output a list of UUIDs of known secrets to stdout.
=back
=head1 ENVIRONMENT
The following environment variables can be set to alter the behaviour

View File

@ -41,6 +41,7 @@
#endif
#include "internal.h"
#include "base64.h"
#include "buf.h"
#include "console.h"
#include "util.h"
@ -271,6 +272,9 @@ static virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
VSH_BYUUID|VSH_BYNAME)
static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd,
char **name);
static void vshPrintExtra(vshControl *ctl, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
static void vshDebug(vshControl *ctl, int level, const char *format, ...)
@ -5249,9 +5253,291 @@ cmdVolPath(vshControl *ctl, const vshCmd *cmd)
}
/*
* "secret-define" command
*/
static const vshCmdInfo info_secret_define[] = {
{"help", gettext_noop("define or modify a secret from an XML file")},
{"desc", gettext_noop("Define or modify a secret.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing secret attributes in XML")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretDefine(vshControl *ctl, const vshCmd *cmd)
{
char *from, *buffer, *uuid;
virSecretPtr res;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", NULL);
if (!from)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
res = virSecretDefineXML(ctl->conn, buffer, 0);
free (buffer);
if (res == NULL) {
vshError(ctl, FALSE, _("Failed to set attributes from %s"), from);
return FALSE;
}
uuid = virSecretGetUUIDString(res);
if (uuid == NULL) {
vshError(ctl, FALSE, "%s",
_("Failed to get UUID of created secret"));
virSecretFree(res);
return FALSE;
}
vshPrint(ctl, _("Secret %s created\n"), uuid);
free(uuid);
virSecretFree(res);
return TRUE;
}
/*
* "secret-dumpxml" command
*/
static const vshCmdInfo info_secret_dumpxml[] = {
{"help", gettext_noop("secret attributes in XML")},
{"desc", gettext_noop("Output attributes of a secret as an XML dump to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_dumpxml[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("secret UUID")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
int ret = FALSE;
char *xml;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
xml = virSecretGetXMLDesc(secret, 0);
if (xml == NULL)
goto cleanup;
printf("%s", xml);
free(xml);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-set-value" command
*/
static const vshCmdInfo info_secret_set_value[] = {
{"help", gettext_noop("set a secret value")},
{"desc", gettext_noop("Set a secret value.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_set_value[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("secret UUID")},
{"base64", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("base64-encoded secret value")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
size_t value_size;
char *base64, *value;
int found, res, ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
base64 = vshCommandOptString(cmd, "base64", &found);
if (!base64)
goto cleanup;
if (!base64_decode_alloc(base64, strlen(base64), &value, &value_size)) {
vshError(ctl, FALSE, _("Invalid base64 data"));
goto cleanup;
}
if (value == NULL) {
vshError(ctl, FALSE, "%s", _("Failed to allocate memory"));
return FALSE;
}
res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0);
memset(value, 0, value_size);
free (value);
if (res != 0) {
vshError(ctl, FALSE, "%s", _("Failed to set secret value"));
goto cleanup;
}
vshPrint(ctl, "%s", _("Secret value set\n"));
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-get-value" command
*/
static const vshCmdInfo info_secret_get_value[] = {
{"help", gettext_noop("Output a secret value")},
{"desc", gettext_noop("Output a secret value to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_get_value[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("secret UUID")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
char *base64;
unsigned char *value;
size_t value_size;
int ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
value = virSecretGetValue(secret, &value_size, 0);
if (value == NULL)
goto cleanup;
base64_encode_alloc((char *)value, value_size, &base64);
memset(value, 0, value_size);
free(value);
if (base64 == NULL) {
vshError(ctl, FALSE, "%s", _("Failed to allocate memory"));
goto cleanup;
}
printf("%s", base64);
memset(base64, 0, strlen(base64));
free(base64);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-undefine" command
*/
static const vshCmdInfo info_secret_undefine[] = {
{"help", gettext_noop("undefine a secret")},
{"desc", gettext_noop("Undefine a secret.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_undefine[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("secret UUID")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
int ret = FALSE;
char *uuid;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, &uuid);
if (secret == NULL)
return FALSE;
if (virSecretUndefine(secret) < 0) {
vshError(ctl, FALSE, _("Failed to delete secret %s"), uuid);
goto cleanup;
}
vshPrint(ctl, _("Secret %s deleted\n"), uuid);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-list" command
*/
static const vshCmdInfo info_secret_list[] = {
{"help", gettext_noop("list secrets")},
{"desc", gettext_noop("Returns a list of secrets")},
{NULL, NULL}
};
static int
cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int maxuuids = 0, i;
char **uuids = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
maxuuids = virConnectNumOfSecrets(ctl->conn);
if (maxuuids < 0) {
vshError(ctl, FALSE, "%s", _("Failed to list secrets"));
return FALSE;
}
uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids);
maxuuids = virConnectListSecrets(ctl->conn, uuids, maxuuids);
if (maxuuids < 0) {
vshError(ctl, FALSE, "%s", _("Failed to list secrets"));
free(uuids);
return FALSE;
}
qsort(uuids, maxuuids, sizeof(char *), namesorter);
vshPrintExtra(ctl, "%s\n", _("UUID"));
vshPrintExtra(ctl, "-----------------------------------------\n");
for (i = 0; i < maxuuids; i++) {
vshPrint(ctl, "%-36s\n", uuids[i]);
free(uuids[i]);
}
free(uuids);
return TRUE;
}
/*
@ -6931,6 +7217,14 @@ static const vshCmdDef commands[] = {
{"pool-undefine", cmdPoolUndefine, opts_pool_undefine, info_pool_undefine},
{"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
{"secret-define", cmdSecretDefine, opts_secret_define, info_secret_define},
{"secret-dumpxml", cmdSecretDumpXML, opts_secret_dumpxml, info_secret_dumpxml},
{"secret-set-value", cmdSecretSetValue, opts_secret_set_value, info_secret_set_value},
{"secret-get-value", cmdSecretGetValue, opts_secret_get_value, info_secret_get_value},
{"secret-undefine", cmdSecretUndefine, opts_secret_undefine, info_secret_undefine},
{"secret-list", cmdSecretList, NULL, info_secret_list},
#ifndef WIN32
{"pwd", cmdPwd, NULL, info_pwd},
#endif
@ -7490,6 +7784,35 @@ vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
return vol;
}
static virSecretPtr
vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, char **name)
{
virSecretPtr secret = NULL;
char *n;
const char *optname = "secret";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
n = vshCommandOptString(cmd, optname, NULL);
if (n == NULL) {
vshError(ctl, FALSE, "%s", _("undefined secret UUID"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n", cmd->def->name, optname, n);
if (name != NULL)
*name = n;
secret = virSecretLookupByUUIDString(ctl->conn, n);
if (secret == NULL)
vshError(ctl, FALSE, _("failed to get secret '%s'"), n);
return secret;
}
/*
* Executes command(s) and returns return code from last command
*/

34
virsh.1
View File

@ -132,7 +132,7 @@
.\" ========================================================================
.\"
.IX Title "VIRSH 1"
.TH VIRSH 1 "2009-08-11" "libvirt-0.7.0" "Virtualization Support"
.TH VIRSH 1 "2009-08-20" "libvirt-0.7.0" "Virtualization Support"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@ -593,6 +593,38 @@ Undefine the configuration for an inactive network.
.IP "\fBnet-uuid\fR \fInetwork-name\fR" 4
.IX Item "net-uuid network-name"
Convert a network name to network \s-1UUID\s0.
.SH "SECRET COMMMANDS"
.IX Header "SECRET COMMMANDS"
The following commands manipulate \*(L"secrets\*(R" (e.g. passwords, passphrases and
encryption keys). Libvirt can store secrets independently from their use, and
other objects (e.g. volumes or domains) can refer to the secrets for encryption
or possibly other uses. Secrets are identified using an \s-1UUID\s0. See
<http://libvirt.org/formatsecret.html> for documentation of the \s-1XML\s0 format
used to represent properties of secrets.
.IP "\fBsecret-define\fR \fIfile\fR" 4
.IX Item "secret-define file"
Create a secret with the properties specified in \fIfile\fR, with no associated
secret value. If \fIfile\fR does not specify a \s-1UUID\s0, choose one automatically.
If \fIfile\fR specifies an \s-1UUID\s0 of an existing secret, replace its properties by
properties defined in \fIfile\fR, without affecting the secret value.
.IP "\fBsecret-dumpxml\fR \fIsecret\fR" 4
.IX Item "secret-dumpxml secret"
Output properties of \fIsecret\fR (specified by its \s-1UUID\s0) as an \s-1XML\s0 dump to stdout.
.IP "\fBsecret-set-value\fR \fIsecret\fR \fIbase64\fR" 4
.IX Item "secret-set-value secret base64"
Set the value associated with \fIsecret\fR (specified by its \s-1UUID\s0) to the value
Base64\-encoded value \fIbase64\fR.
.IP "\fBsecret-get-value\fR \fIsecret\fR" 4
.IX Item "secret-get-value secret"
Output the value associated with \fIsecret\fR (specified by its \s-1UUID\s0) to stdout,
encoded using Base64.
.IP "\fBsecret-undefine\fR \fIsecret\fR" 4
.IX Item "secret-undefine secret"
Delete a \fIsecret\fR (specified by its \s-1UUID\s0), including the associated value, if
any.
.IP "\fBsecret-list\fR" 4
.IX Item "secret-list"
Output a list of UUIDs of known secrets to stdout.
.SH "ENVIRONMENT"
.IX Header "ENVIRONMENT"
The following environment variables can be set to alter the behaviour