Add a command which allows to read a secret value from terminal.
'secret-passwd' is chosen as a name as the password has limitations as
passwords do have (printable, terminated by newline which is not
contained in the value). This makes it way more user-friendly to use the
secret driver with virsh when setting a value.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
docs/manpages/virsh.rst | 15 +++++++++
tools/virsh-secret.c | 70 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 6446a903ca..03364684b5 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -6564,6 +6564,21 @@ Set the value associated with *secret* (specified by its UUID) to
the value
Base64-encoded value *base64*.
+secret-passwd
+----------------
+
+**Syntax:**
+
+.. code-block::
+
+ secret-passwd secret
+
+Set the value associated with *secret* (specified by its UUID) to a string
+read from stdin. Note that input is terminated by a newline and the secret
+can't contain non-printable characters. Use *secret-set-value* for generic
+secrets. Note that this requires a terminal associated with virsh to read
+the password.
+
secret-get-value
----------------
diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c
index 66369a25dc..9f64be6b14 100644
--- a/tools/virsh-secret.c
+++ b/tools/virsh-secret.c
@@ -219,6 +219,70 @@ cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+
+/*
+ * "secret-passwd" command
+ */
+static const vshCmdInfo info_secret_passwd[] = {
+ {.name = "help",
+ .data = N_("set a secret value from stdin")
+ },
+ {.name = "desc",
+ .data = N_("Set a secret value from stdin")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_secret_passwd[] = {
+ {.name = "secret",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("secret UUID"),
+ .completer = virshSecretUUIDCompleter,
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdSecretPasswd(vshControl *ctl,
+ const vshCmd *cmd)
+{
+ virSecretPtr secret;
+ g_autofree char *value = NULL;
+ int res;
+ bool ret = false;
+
+ if (!ctl->istty) {
+ vshError(ctl, "%s", _("secret-passwd requires a terminal"));
+ return false;
+ }
+
+ if (!(secret = virshCommandOptSecret(ctl, cmd, NULL)))
+ return false;
+
+ vshPrint(ctl, "%s", _("Enter new value for secret:"));
+ fflush(stdout);
+
+ if (!(value = getpass(""))) {
+ vshError(ctl, "%s", _("Failed to read secret"));
+ goto cleanup;
+ }
+
+ res = virSecretSetValue(secret, (unsigned char *) value, strlen(value), 0);
+
+ if (res != 0) {
+ vshError(ctl, "%s", _("Failed to set secret value"));
+ goto cleanup;
+ }
+ vshPrintExtra(ctl, "%s", _("Secret value set\n"));
+ ret = true;
+
+ cleanup:
+ virSecretFree(secret);
+ return ret;
+}
+
+
/*
* "secret-get-value" command
*/
@@ -805,6 +869,12 @@ const vshCmdDef secretCmds[] = {
.info = info_secret_set_value,
.flags = 0
},
+ {.name = "secret-passwd",
+ .handler = cmdSecretPasswd,
+ .opts = opts_secret_passwd,
+ .info = info_secret_passwd,
+ .flags = 0
+ },
{.name = "secret-undefine",
.handler = cmdSecretUndefine,
.opts = opts_secret_undefine,
--
2.24.1