[PATCH 0/6] Introduce OpenSSH authorized key file mgmt APIs

Peter Krempa pkrempa at redhat.com
Thu Nov 12 14:46:47 UTC 2020


On Thu, Nov 12, 2020 at 12:55:23 +0100, Michal Privoznik wrote:
> On 11/11/20 1:04 PM, Michal Privoznik wrote:
> > On 11/11/20 11:32 AM, Peter Krempa wrote:
> > > On Tue, Nov 10, 2020 at 16:11:40 +0100, Michal Privoznik wrote:
> > > > Marc-André posted a patch that implements agent handling. I've written
> > > > the rest.
> > > > 
> > > > Marc-André Lureau (1):
> > > >    qemu_agent: add qemuAgentSSH{Add,Remove,Get}AuthorizedKeys
> > > > 
> > > > Michal Prívozník (5):
> > > >    Introduce OpenSSH authorized key file mgmt APIs
> > > 
> > > One more thing to think about:
> > > 
> > > Since we are getting random requests for setters of various bits which
> > > we have to bend the rule "we don't care what's running in the VM" and
> > > which don't really scale when adding new APIs. I propose we add a
> > > generic guest agent setter which will be extensible using a typed
> > > parameters and a type property.
> > > 
> > > It will basically become the counterpart to virDomainGetGuestInfo.
> > > 
> > > The extensions then become enum additions and code additions only and
> > > will be more flexible for future use.
> > > 
> > > The same way the getter forthe ssh keys should become part of
> > > virDomainGetGuestInfo, obviously auditing whether a read-write
> > > connection is used.
> > > 
> > > example:
> > > 
> > > int
> > > qemuDomainSetGuestInfo(virDomainPtr dom,
> > >                         virDomainSetGuestInfoType type,
> > >                         virTypedParamPtr params,
> > >                         unsigned int  nparams,
> > >                         unsigned int flags);
> > > 
> > > Invocation for setting keys:
> > > 
> > > virTypedParamsAddString(..., "user", "root")
> > > virTypedParamsAddString(..., "key", "ssh-rsa AA.... root at localhost")
> > > virTypedParamsAddString(..., "key", "ssh-rsa AA.... user at localhost")
> > > 
> > > etc.
> > > 
> > 
> > Yeah, this is much more extensible. Okay, let me send v2.
> 
> My enthusiasm might had been premature. virDomainGetGuestInfo() does not
> send anything but virDomainPtr, unsigned int types and flags down the wire.
> While we can make @params be both in and out type of arguments, it's going
> to require change of RPC. I mean the way that qemu-ga APIs are implemented
> is that for listing ssh keys the API expects an user on the input so that it
> can construct $HOME/.ssh/authorized_keys path. How to pass this through
> virDomainGetGuestInfo()? Okay, we could work around it by just listing SSH
> keys for all users and let caller filter our the interesting ones, but this
> is: a) scary from security POV,  b) suboptimal because we might hit message
> size limit pretty soon. Also, there is no qemu-ga API to list all users,
> just those logged in currently. And the whole point of these new APIs is to
> set up SSH keys before user logs in.

Yeah, using virDomainGetGuestInfo as the getter for the keys will not
work.

What I ultimately want to suggest is something more generic which will
allow driving guest agent APIs libvirt doesn't actually care about
without having to add single-use APIs for every single one of them.

qemu-ga seems to support following APIs:

$ ./qemu-ga --blacklist=?
guest-sync-delimited
guest-sync
guest-ping
guest-get-time
guest-set-time
guest-info
guest-shutdown
guest-file-open
guest-file-close
guest-file-read
guest-file-write
guest-file-seek
guest-file-flush
guest-fsfreeze-status
guest-fsfreeze-freeze
guest-fsfreeze-freeze-list
guest-fsfreeze-thaw
guest-fstrim
guest-suspend-disk
guest-suspend-ram
guest-suspend-hybrid
guest-network-get-interfaces
guest-get-vcpus
guest-set-vcpus
guest-get-disks
guest-get-fsinfo
guest-set-user-password
guest-get-memory-blocks
guest-set-memory-blocks
guest-get-memory-block-info
guest-exec-status
guest-exec
guest-get-host-name
guest-get-users
guest-get-timezone
guest-get-osinfo
guest-get-devices
guest-ssh-get-authorized-keys
guest-ssh-add-authorized-keys
guest-ssh-remove-authorized-keys


Let's categorize them:

Utility functions:
guest-sync-delimited
guest-sync
guest-ping

Functions which at least partially map to libvirt APIs:
guest-shutdown
guest-get-vcpus
guest-set-vcpus

Functions used internally but also useful externally:
guest-fsfreeze-status
guest-fsfreeze-freeze
guest-fsfreeze-freeze-list
guest-fsfreeze-thaw

Functions which can be claimed to map to libvirt but don't really:
guest-suspend-disk
guest-suspend-ram
guest-suspend-hybrid

Functions which are not really relevant to libvirt but we expose wrappers:
guest-get-time
guest-set-time
guest-fstrim
guest-network-get-interfaces
guest-get-disks
guest-get-fsinfo
guest-get-host-name
guest-get-users
guest-get-timezone
guest-get-osinfo

Functions which are not really relevant to libvirt, we expose wrappers
and they are scary:
guest-set-user-password

Functions which are not really relevant to libvirt, we don't expose wrappers
and they are scary:
guest-file-open
guest-file-close
guest-file-read
guest-file-write
guest-file-seek
guest-file-flush
guest-exec-status
guest-exec

Other stats functions we might be asked for:
guest-info
guest-get-memory-blocks
guest-set-memory-blocks
guest-get-memory-block-info
guest-get-devices

And finally those we have here:
guest-ssh-get-authorized-keys
guest-ssh-add-authorized-keys
guest-ssh-remove-authorized-keys

So there's just a very tiny set of QGA APIs we really need.

For the rest we are adding more-or-less direct wrappers to satisfy the
access to the APIs.

With more-and-more APIs added which really deal just with the guest
state itself it's a bit weird to add libvirt APIs for them.

I'd like us to prevent adding new APIs constantly especially those which
deal just with the guest.

Since libvirt actually can't ever rely on the state of the guest agent
as it can be restarted at any time including the guest OS and thus we
we have to internally treat it without any presumptions about state and
re-probe everything and we really need just a tiny
subset of the commands, we'd really benefint from just multiplexing access
between libvirt and any other APP which can use the QGA QMP protocol
directly.

Thus I think we could arguably make virDomainQemuAgentCommand a
supported API. Any guest state change which can be initiated via the GA
needs to be supported also without that since the guest itself can
trigger it.

Saying that virDomainQemuAgentCommand is fully supported to be used
would free us from having to add arbitrary unextendable APIs for every
single guest agent API, but would still allow libvirt to use APIs we
need.

We just need to make 100% sure that it can't be abused as argument to
to change status of virDomainQemuMonitorCommand.




More information about the libvir-list mailing list