coreos / rpm-ostree

⚛📦 Hybrid image/package system with atomic upgrades and package layering
https://coreos.github.io/rpm-ostree
Other
872 stars 195 forks source link

Support delegation of privilege using `LoadCredential=`, add socket activation #3850

Open cgwalters opened 2 years ago

cgwalters commented 2 years ago

A while ago we had this thread on systemd-devel: https://lists.freedesktop.org/archives/systemd-devel/2021-February/046113.html

Basically today we have zincati statically allocate a uid that is referenced from a polkit policy. Instead, if we expose an AF_UNIX socket that writes a random token, services like zincati can use e.g. LoadCredential=/run/rpm-ostree.token and pass that to us in order to authenticate at run time to perform privileged operations.

This way zincati can switch to using DynamicUser=yes i.e. we don't have a zincati in /etc/passwd - and we can drop the polkit rule (and FCOS' dependency on polkit).

Additionally, I think this is the pattern we want to use for privilege separating our own process, instead of the approach taken in https://github.com/coreos/rpm-ostree/pull/3239

cgwalters commented 2 years ago

Strongly related to this is moving away from DBus towards being socket activated. This was previously attempted in https://github.com/coreos/rpm-ostree/pull/2932 and I still really think we should do this.

It would have entirely avoided the comedy of errors here from https://github.com/coreos/rpm-ostree/pull/2945 to https://github.com/coreos/rpm-ostree/pull/3523 to then later realizing we never shipped that in rhel8 until it all blew up.

cgwalters commented 2 years ago

It looks like LoadCredential= is in RHEL9.0, so we can aim for a hard cutover here.

jlebon commented 2 years ago

A while ago we had this thread on systemd-devel: lists.freedesktop.org/archives/systemd-devel/2021-February/046113.html

Basically today we have zincati statically allocate a uid that is referenced from a polkit policy. Instead, if we expose an AF_UNIX socket that writes a random token, services like zincati can use e.g. LoadCredential=/run/rpm-ostree.token and pass that to us in order to authenticate at run time to perform privileged operations.

So in this model, can any system service use LoadCredential in their systemd unit and gain full privileges? The nice thing with the current polkit approach is that we're poking a hole just the size we need (up to the specific polkit actions required).

cgwalters commented 2 years ago

So in this model, can any system service use LoadCredential in their systemd unit and gain full privileges?

We can offer multiple sockets (credentials).

(Any systemd service today defaults to full privileges in their ExecStart=, we're not doing anything they can't do)

jlebon commented 2 years ago

So in this model, can any system service use LoadCredential in their systemd unit and gain full privileges?

We can offer multiple sockets (credentials).

IIUC, a major difference is that this knowledge would live in our code, not in the Zincati code which I guess is a tradeoff. Though I could imagine a generic "update driver" socket with permissions we expect drivers to want.

(Any systemd service today defaults to full privileges in their ExecStart=, we're not doing anything they can't do)

Yeah, I'm not too concerned about that. I just really like how with polkit, Zincati can declare exactly only what it needs.

If we're planning on maintaining polkit support, it would be good to not have multiple authentication and authorization mechanisms. How DynamicUser=yes + polkit should work together seems like a more generic issue though than just us.

cgwalters commented 2 years ago

Just to xref, https://github.com/coreos/coreos-assembler/issues/1301 was another variant of the DBus activation and timeout stuff that would have been fixed by this.