mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
virsh: Expose OpenSSH authorized key file mgmt APIs
The new virsh commands are: get-user-sshkeys set-user-sshkeys Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
40c35dfa1f
commit
87d12effbe
@ -2636,6 +2636,21 @@ When *--timestamp* is used, a human-readable timestamp will be printed
|
|||||||
before the event.
|
before the event.
|
||||||
|
|
||||||
|
|
||||||
|
get-user-sshkeys
|
||||||
|
----------------
|
||||||
|
|
||||||
|
**Syntax:**
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
get-user-sshkeys domain user
|
||||||
|
|
||||||
|
Print SSH authorized keys for given *user* in the guest *domain*. Please note,
|
||||||
|
that an entry in the file has internal structure as defined by *sshd(8)* and
|
||||||
|
virsh/libvirt does handle keys as opaque strings, i.e. does not interpret
|
||||||
|
them.
|
||||||
|
|
||||||
|
|
||||||
guest-agent-timeout
|
guest-agent-timeout
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -4004,6 +4019,29 @@ For QEMU/KVM, this requires the guest agent to be configured
|
|||||||
and running.
|
and running.
|
||||||
|
|
||||||
|
|
||||||
|
set-user-sshkeys
|
||||||
|
----------------
|
||||||
|
|
||||||
|
**Syntax:**
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
set-user-sshkeys domain user [--file FILE] [{--reset | --remove}]
|
||||||
|
|
||||||
|
Append keys read from *FILE* into *user*'s SSH authorized keys file in the
|
||||||
|
guest *domain*. In the *FILE* keys must be on separate lines and each line
|
||||||
|
must follow authorized keys format as defined by *sshd(8)*.
|
||||||
|
|
||||||
|
If *--reset* is specified, then the guest authorized keys file content is
|
||||||
|
removed before appending new keys. As a special case, if *--reset* is provided
|
||||||
|
and no *FILE* was provided then no new keys are added and the authorized keys
|
||||||
|
file is cleared out.
|
||||||
|
|
||||||
|
If *--remove* is specified, then instead of adding any new keys then keys read
|
||||||
|
from *FILE* are removed from the authorized keys file. It is not considered an
|
||||||
|
error if the key does not exist in the file.
|
||||||
|
|
||||||
|
|
||||||
setmaxmem
|
setmaxmem
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -14263,6 +14263,158 @@ cmdGuestInfo(vshControl *ctl, const vshCmd *cmd)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "get-user-sshkeys" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_get_user_sshkeys[] = {
|
||||||
|
{.name = "help",
|
||||||
|
.data = N_("list authorized SSH keys for given user (via agent)")
|
||||||
|
},
|
||||||
|
{.name = "desc",
|
||||||
|
.data = N_("Use the guest agent to query authorized SSH keys for given "
|
||||||
|
"user")
|
||||||
|
},
|
||||||
|
{.name = NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_get_user_sshkeys[] = {
|
||||||
|
VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE),
|
||||||
|
{.name = "user",
|
||||||
|
.type = VSH_OT_DATA,
|
||||||
|
.flags = VSH_OFLAG_REQ,
|
||||||
|
.help = N_("user to list authorized keys for"),
|
||||||
|
},
|
||||||
|
{.name = NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdGetUserSSHKeys(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
const char *user;
|
||||||
|
VIR_AUTOSTRINGLIST keys = NULL;
|
||||||
|
int nkeys = 0;
|
||||||
|
size_t i;
|
||||||
|
const unsigned int flags = 0;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptStringReq(ctl, cmd, "user", &user) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
nkeys = virDomainAuthorizedSSHKeysGet(dom, user, &keys, flags);
|
||||||
|
if (nkeys < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < nkeys; i++) {
|
||||||
|
vshPrint(ctl, "%s", keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
cleanup:
|
||||||
|
virshDomainFree(dom);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "set-user-sshkeys" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_set_user_sshkeys[] = {
|
||||||
|
{.name = "help",
|
||||||
|
.data = N_("manipulate authorized SSH keys file for given user (via agent)")
|
||||||
|
},
|
||||||
|
{.name = "desc",
|
||||||
|
.data = N_("Append, reset or remove specified key from the authorized "
|
||||||
|
"keys file for given user")
|
||||||
|
},
|
||||||
|
{.name = NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_set_user_sshkeys[] = {
|
||||||
|
VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE),
|
||||||
|
{.name = "user",
|
||||||
|
.type = VSH_OT_DATA,
|
||||||
|
.flags = VSH_OFLAG_REQ,
|
||||||
|
.help = N_("user to set authorized keys for"),
|
||||||
|
},
|
||||||
|
{.name = "file",
|
||||||
|
.type = VSH_OT_STRING,
|
||||||
|
.help = N_("optional file to read keys from"),
|
||||||
|
},
|
||||||
|
{.name = "reset",
|
||||||
|
.type = VSH_OT_BOOL,
|
||||||
|
.help = N_("clear out authorized keys file before adding new keys"),
|
||||||
|
},
|
||||||
|
{.name = "remove",
|
||||||
|
.type = VSH_OT_BOOL,
|
||||||
|
.help = N_("remove keys from the authorized keys file"),
|
||||||
|
},
|
||||||
|
{.name = NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdSetUserSSHKeys(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
const char *user;
|
||||||
|
const char *from;
|
||||||
|
g_autofree char *buffer = NULL;
|
||||||
|
VIR_AUTOSTRINGLIST keys = NULL;
|
||||||
|
int nkeys = 0;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
VSH_REQUIRE_OPTION("remove", "file");
|
||||||
|
VSH_EXCLUSIVE_OPTIONS("reset", "remove");
|
||||||
|
|
||||||
|
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptStringReq(ctl, cmd, "user", &user) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!vshCommandOptBool(cmd, "reset")) {
|
||||||
|
flags |= VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_APPEND;
|
||||||
|
|
||||||
|
if (!from) {
|
||||||
|
vshError(ctl, _("Option --file is required"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vshCommandOptBool(cmd, "remove"))
|
||||||
|
flags |= VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_REMOVE;
|
||||||
|
|
||||||
|
if (from) {
|
||||||
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) {
|
||||||
|
vshSaveLibvirtError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(keys = virStringSplit(buffer, "\n", -1)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
nkeys = virStringListLength((const char **) keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainAuthorizedSSHKeysSet(dom, user,
|
||||||
|
(const char **) keys, nkeys, flags) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
cleanup:
|
||||||
|
virshDomainFree(dom);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const vshCmdDef domManagementCmds[] = {
|
const vshCmdDef domManagementCmds[] = {
|
||||||
{.name = "attach-device",
|
{.name = "attach-device",
|
||||||
.handler = cmdAttachDevice,
|
.handler = cmdAttachDevice,
|
||||||
@ -14530,6 +14682,12 @@ const vshCmdDef domManagementCmds[] = {
|
|||||||
.info = info_event,
|
.info = info_event,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
},
|
},
|
||||||
|
{.name = "get-user-sshkeys",
|
||||||
|
.handler = cmdGetUserSSHKeys,
|
||||||
|
.opts = opts_get_user_sshkeys,
|
||||||
|
.info = info_get_user_sshkeys,
|
||||||
|
.flags = 0
|
||||||
|
},
|
||||||
{.name = "inject-nmi",
|
{.name = "inject-nmi",
|
||||||
.handler = cmdInjectNMI,
|
.handler = cmdInjectNMI,
|
||||||
.opts = opts_inject_nmi,
|
.opts = opts_inject_nmi,
|
||||||
@ -14776,6 +14934,12 @@ const vshCmdDef domManagementCmds[] = {
|
|||||||
.info = info_setLifecycleAction,
|
.info = info_setLifecycleAction,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
},
|
},
|
||||||
|
{.name = "set-user-sshkeys",
|
||||||
|
.handler = cmdSetUserSSHKeys,
|
||||||
|
.opts = opts_set_user_sshkeys,
|
||||||
|
.info = info_set_user_sshkeys,
|
||||||
|
.flags = 0
|
||||||
|
},
|
||||||
{.name = "set-user-password",
|
{.name = "set-user-password",
|
||||||
.handler = cmdSetUserPassword,
|
.handler = cmdSetUserPassword,
|
||||||
.opts = opts_set_user_password,
|
.opts = opts_set_user_password,
|
||||||
|
Loading…
Reference in New Issue
Block a user