-
Notifications
You must be signed in to change notification settings - Fork 1.2k
shell: add run0 as a sudo alternative #22373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
martinpitt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously needs integration tests, but I suppose you asked for review to discuss the design?
pkg/shell/manifest.json
Outdated
| "spawn": [ | ||
| "run0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we do any kind of "does that binary exist?" check anywhere? I thought we didn't, and on non-bleeding-edge distros that would just fail superuser.
Also, I don't think we are ready to replace sudo as default yet. Adding run0 as an option is great and desirable, but breaking existing setups with custom sudo rules very much isn't. And they are very popular, e.g. a lot of cloud instances have them, or even with NOPASSWD.
If we do this, I think we'll have to bite the bullet of adding an availability check to the manifest, and check if sudo is the "good" one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need something like path-exists maybe? For sure rhel-8-10 won't have it run0. I would love to opt in to run0 for, for example my own server would love to use run0. So maybe we should figure out either:
- a way to fallback in case of a broken
sudo - a way to set your preferred
superuser provider, although that brings in my configuration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a way to do that (https://cockpit-project.org/guide/latest/packages.html#manifest-overrides), but it's not very well documented . Check testMultipleBridgeConfig.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but that wouldn't work with Cockpit client ;-)
|
TBH the only way I see us migrating away from sudo by default is to keep sudo on upgrades, and switching to run0 (if available) or pkexec on new installs. This is a bit involved, but we e.g. did it for |
|
What's the specific concern about not using sudo? Do you imagine someone has added Or is it more about adding users who aren't in the wheel group? |
|
My take: we should use run0 if it exists, otherwise fall back to sudo. The exact mechanism by which we implement that is a "smop" as pitti likes to say :) But yes: an override could work for existing installs. I just want to make sure we all agree about if and why it's necessary. |
|
I'm less concerned about command restriction sudo rules, but more about custom sudo rules like you commonly find on e.g. cloud images (as said above): I.e. which aren't based on our standard wheel/sudo groups, but direct names. run0/pkexec don't catch these. |
facd81b to
53788b6
Compare
|
Shouldn't we just merge this with a new test in |
Yes. This is a good first step. |
53788b6 to
01850b0
Compare
martinpitt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Some small questions, but this looks very sane (needs test cases of course)
| if (ids.length == 0) | ||
| start("sudo"); | ||
| start(proxy.Bridges[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't checked how this all hangs together, but this reads odd .. Is it guaranteed that Bridges[0] exists here, if there are no IDs? I.e. does "id" just mean "labelled bridge" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. The Methods (ie: the ids in this function) are the bridges that have labels. The Bridges are the names of all bridges, labels or not.
It's actually possible that we'd have no bridges (if none of run0, sudo, or pkexec appear in the path) so maybe we should indeed check for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK we don't currently check if the bridge actually exists, no? So this could only happen with a manifest override that removes all superuser bridges. That's actually not an unreasonable thing to do for things like e.g. clouddot (remember that still?) or foreman integration, or other custom setups.
src/cockpit/superuser.py
Outdated
| self.stop() | ||
| self.shutdown() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that make a practical difference? Does it matter here, or is it unrelated cleanup similar to the Optional[] typing changes? (I don't mind, just want to understand it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was a typing thing: the .stop() method is wrapped as a D-Bus method and the decorator erases the typing information. Since .stop() just calls .shutdown() directly anyway (which is correctly typed) we can avoid the error about calling an untyped function. I should have explained that in the commit message better, but the inclusion of the typing stuff here at all was an unintentional rebase fail..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, thanks!
01850b0 to
47ef97b
Compare
| b.wait_not_present(".pf-v6-c-modal-box:contains('Switch to administrative access')") | ||
| b.check_superuser_indicator("Administrative access") | ||
|
|
||
| # Verify run0 is being used and not sudo or pkexec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no check for "not using sudo" here, actually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shakes fist claude!
If the argv[0] of a bridge doesn't exist in the path then remove it from the list. In the shell superuser dialog we first look if `Methods` are available (which is when the user provides `"label"` keys on their superuser entries, which is not the default). If not, or if the number of labels is zero, we fall back to using the string "sudo". With the change to remove methods that are not available, "sudo" may no longer be the first available method, so fall back to the first available method. Also add an explicit error path for the case that no methods are available. Make a minor UI tweak: now that we have an error dialog for no methods being available, always show the indicator (even if there are no methods available) so that the user can still see "Limited access" and click on it to find out why. We need to change a type annotation: I'm not sure why this ended up being declared unknown, but the D-Bus type of the thing is `as` so `string[]` is definitely the right choice here. Use Claude to write a testcase. Assisted-by: Claude <[email protected]>
If we detect a version of sudo which lacks support for the -A (askpass) flag then we exclude it from the list of available authentication methods. This prevents us from trying to use sudo-rs, which lacks askpass support (which we depend on). See trifectatechfoundation/sudo-rs#1249
This was surprisingly easy: we just needed to enable our already-existing polkit agent for "run0" as we have it for "pkexec". Add run0 in the order below sudo but above pkexec. This means that on systems without a working sudo (such as Ubuntu 25.10) but run0 present, we will choose run0. The eventual goal will be to default to run0 but let's try this as a first step. This will help us in our beautiful post-setuid future. Closes cockpit-project#21723
Add tests to verify run0 works as a fallback when sudo is unavailable or broken: - test_run0_no_sudo: sudo removed entirely - test_run0_broken_sudo: sudo doesn't support askpass - test_run0_wrong_password: verify wrong password handling with run0 Assisted-by: Claude <[email protected]>
47ef97b to
b90548b
Compare


This was surprisingly easy: we just needed to enable our already-existing polkit agent for "run0" as we have it for "pkexec".
This will help us in our beautiful post-setuid future.
Closes #21723
The patch is trivial, but there's gonna need to be some discussion here...