mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00: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.
|
||||
|
||||
|
||||
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
|
||||
-------------------
|
||||
|
||||
@ -4004,6 +4019,29 @@ For QEMU/KVM, this requires the guest agent to be configured
|
||||
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
|
||||
---------
|
||||
|
||||
|
@ -14263,6 +14263,158 @@ cmdGuestInfo(vshControl *ctl, const vshCmd *cmd)
|
||||
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[] = {
|
||||
{.name = "attach-device",
|
||||
.handler = cmdAttachDevice,
|
||||
@ -14530,6 +14682,12 @@ const vshCmdDef domManagementCmds[] = {
|
||||
.info = info_event,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "get-user-sshkeys",
|
||||
.handler = cmdGetUserSSHKeys,
|
||||
.opts = opts_get_user_sshkeys,
|
||||
.info = info_get_user_sshkeys,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "inject-nmi",
|
||||
.handler = cmdInjectNMI,
|
||||
.opts = opts_inject_nmi,
|
||||
@ -14776,6 +14934,12 @@ const vshCmdDef domManagementCmds[] = {
|
||||
.info = info_setLifecycleAction,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "set-user-sshkeys",
|
||||
.handler = cmdSetUserSSHKeys,
|
||||
.opts = opts_set_user_sshkeys,
|
||||
.info = info_set_user_sshkeys,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "set-user-password",
|
||||
.handler = cmdSetUserPassword,
|
||||
.opts = opts_set_user_password,
|
||||
|
Loading…
Reference in New Issue
Block a user