If you define a secret with private="yes", then libvirt won't let any
client query the secret value after it is set. Only other libvirt
drivers inside the daemon can query it by passing a special internal
only flag to the virSecretGetValue API. The remote driver/daemon
refuses to let this internal flag go over the wire preventing normal
clients from using it
This doesn't work with the split daemons because the virSecretGetValue
API done by virqemud / virtstoraged has to go over the wire to reach
the virsecretd.
We need to come up with an alternative way to "prove" that the caller
of virSecretGetValue is a libvirt daemon, as opposed to a general
libvirt client.
Note with if only traditional POSIX DAC permissions are in effect
then we could consider it pointless trying to restrict access to
clients running the same user/group as the libvirt daemon. We ought
to take into account that the client might be confined by SELinux
though, so the "private secret" concept isn't entirely pointless.
Thus doing a simple uid of client == uid of daemon check is a bit
too weak. The UID check might also not fly if the modular daemons
are run inside containers with user namespaces, as the container
for virtsecretd and virtqemud might have different user mappings
in theory.
This series adds a concept of a "token" which is known only to the
libvirt daemons. The first daemon to use it writes a random hex
string to /var/run/libvirt/common/system.token. Other daemons can
read and compare this. Unless a MAC system is present this is still
largely security theatre, but that's not really worse than the
historical behaviour.
When an API call is made the virIdentity by default reflects the
identity of the UNIX process that initiated it.
When connecting to virtproxyd, the client apps' identity is forwarded
to the next virtNNNNd daemon.
When libvirt drivers, however, initiate an API call we never set any
identity. With monolithic libvirtd, they'd inherit the current client
identity automagically since it was all in the same thread local. With
modular daemons the othe driver would see the identity of the other
libvirt daemon which is bad as this gives elevated privileges in the
ACL check.
Thus we fix the code which drivers use to open a connection to other
daemons, such that it applies the current caller's identity. It does
this using an "elevated" identity though, which means, we have added
in the system token. Thus the virtsecretd daemon getting the call
virSecretGetValue sees the virIdentity reflecting the client
application which originally called the virDomainCreate() API, but
with the system token set. Thus virsecretd can see that the
virSecretGetValue was invoked by another daemon, not a libvirt
client app.
Daniel P. Berrangé (9):
util: add virRandomToken API
util: introduce concept of a system token into identities
util: generate a persistent system token
src: set system token for system identity
util: add API for copying identity objects
util: add method for getting the current identity with system token
src: add API to determine if current identity is a system identity
secret: rework handling of private secrets
src: set identity when opening secondary drivers
src/driver-secret.h | 9 +-
src/driver.c | 27 +++++
src/libvirt-secret.c | 2 +-
src/libvirt_private.syms | 5 +
src/remote/remote_driver.c | 8 +-
src/secret/secret_driver.c | 34 ++++--
src/util/viridentity.c | 230 +++++++++++++++++++++++++++++++++++++
src/util/viridentity.h | 7 ++
src/util/virrandom.c | 18 +++
src/util/virrandom.h | 1 +
src/util/virsecret.c | 3 +-
tests/qemuxml2argvtest.c | 3 +-
12 files changed, 320 insertions(+), 27 deletions(-)
--
2.31.1