Configuration file for easier customization and modify downgrade execution workflow with assumption (and enforcement) of root permissions
atreyasha opened this issue Β· comments
This issue proposes the introduction of user-specific configuration file(s) in order to customize the behaviour of downgrade
. This is becoming increasingly important as downgrade
incorporates more diverse features. Below are some points that could be included in a corresponding PR:
-
I would propose naming the configuration file as
downgrade.conf
and placing it in~/.config/downgrade
. -
For consistency and (prospective) easy debugging, we could deprecate the command-line input of environmental variables such as
DOWNGRADE_NOSUDO=1 downgrade
and instead fix the environmental variables as defaults withindowngrade
by replacing the:=
variable assignment operator with=
. The only way to change environmental variables insidedowngrade
would be via CLI options and/or a configuration file. -
We set the assignment order of environmental variables to be -> first set them to defaults as per
downgrade
, then update them with user-specific configuration files, then update them by any CLI options supplied. -
Include
man 5
entry for the syntax of this configuration file.
Sounds good to me.
I just had an idea that might simplify things: what if we only support altering downgrade behavior through command-line flags, and the configuration file can just pre-specify them? This is how (e.g.) reflector works:
# /etc/xdg/reflector/reflector.conf
--save /etc/pacman.d/mirrorlist
--country France,Germany
--protocol https
--latest 5
I could see a very similar thing:
--pacman-conf /etc/foo/bar.conf
--nosudo
I also wonder if we should re-visit the idea of downgrade
being invoked by a user and then internally using sudo
(or su root
) to execute root-level commands. It might be simpler for downgrade
to assume a system-level governance (it's basically a pacman
operation right?) and so assume it will itself be called by root. This would simplify away the --nosudo
functionality nicely. If we did that, the configuration file should probably be system-wide, at /etc/xdg/downgrade/downgrade.conf
-- again following Reflector's lead here. We could install a sample too.
I just had an idea that might simplify things: what if we only support altering downgrade behavior through command-line flags, and the configuration file can just pre-specify them?
π for this, it is indeed much simpler and quicker to implement.
I also wonder if we should re-visit the idea of downgrade being invoked by a user and then internally using sudo (or su root) to execute root-level commands. It might be simpler for downgrade to assume a system-level governance (it's basically a pacman operation right?) and so assume it will itself be called by root. This would simplify away the --nosudo functionality nicely. If we did that, the configuration file should probably be system-wide, at /etc/xdg/downgrade/downgrade.conf -- again following Reflector's lead here. We could install a sample too.
Hmm, I am not sure because I did not think of this much before. But what was the original purpose of having the --nosudo
option? Was it for users who don't want to use sudo
or always operate as root
?
I agree that downgrade
is essentially a pacman
level operation. So it does make sense to fully realize that assumption, which would motivate removing the --nosudo
option and using a configuration file present somewhere in /etc
.
That would also mean we remove the sudo
pre-commands within downgrade
, particularly for the code segments below. With the removal of sudo
in those code chunks, we would need to check root permissions (possibly with id -u
) before downgrade
is executed and exit if root permissions are not present, similar to calling pacman
without root permissions. WDYT?
But what was the original purpose of having the --nosudo option? Was it for users who don't want to use sudo or always operate as root?
It's sort of tangential. Downgrade always expected to operate as user and escalate to root for certain commands. How it did that was either by sudo
(if installed) or su
otherwise, automatically. --nosudo
just let's a user choose not to use sudo
even if it's installed. I doubt anyone ever used this feature.
That would also mean we remove the sudo pre-commands within downgrade
Minor nit-pick, but I want to mention it to ensure we don't have any larger misunderstandings: there is no also here; this is the entire idea. Downgrade should assume (and enforce) it's run as root.
we would need to check root permissions
Yup! If we did this, I would expect the first line of downgrade
to be something like:
if ((USER)); then
echo "downgrade must be run as root" >&2
exit 1
fi
We might have a few wrinkles in the test suite, but I think they could be worked out pretty easily.
Makes sense, and thanks for the clarification :)
@pbrisbin quick question regarding the configuration file part of this issue, which I'd like to work on next.
As we discussed before, we could place a default configuration file as /etc/xdg/downgrade/downgrade.conf
following the example of Reflector.
Does it make sense to add a command-line argument where the user could specify an alternative configuration file? I can imagine an edge case where downgrade
is installed on a system with several users having sudo
access. Not sure how likely such a setting would be, but in this case each user would benefit from an individual configuration file for, say, their own package caches.
Yes, I think it makes sense, eventually. I would look at this as 3 changes we can implement in turn:
1, Ship and respect a global file
2. Respect a user-specific file instead (in a fixed location), if present
3. Support changing the user-specific file location
Once you do get to step 3, I would probably suggested an environment variable instead of a command-line flag. Since the idea for the configuration format is to just hold command-line flags, you might get into some circular complexities given that it's theoretically possible to specify a config location via a config.
Additionally, a command-line flag to ignore the user-specific file even if present, and fall back to the global file, could be useful. But again, I'd hold off on implementation of too much too soon, or you risk adding features no one actually uses.
1, Ship and respect a global file
2. Respect a user-specific file instead (in a fixed location), if present
3. Support changing the user-specific file location
SGTM. I am thinking of combining points (1) and (2) in this PR, as they seem quite complementary. As you mentioned, (3) involves additional complexity and it seems like something that won't be heavily used; so we can pass on it for now.
In any case, I am almost done with coding (1) and now moving on to (2). Am encountering a small issue which I would like to discuss with you.
As per #144, we made downgrade
a root-level operation. This means that user-specific environmental variables such as $HOME
no longer imply the actual user but instead root. This would make it difficult to identify the user-specific downgrade configuration file using for eg. $HOME/.config/downgrade.conf
. I found some workarounds here which essentially use logname
to identify the non-root user behind sudo
. But there are many pitfalls as mentioned in the link.
These workarounds to make (2) work seem too hack'ish and unsafe for me. WDYT?
Alternatively, we could drop (2) and (3) altogether and only permit the use of a single root-level configuration file. The pitfall there would be cases where users have their own caches with duplicate packages across caches, in which case downgrade
would show duplicate packages in the selection menu. This could be addressed by us adding a new column in the menu with trimmed paths to the package directories, which would help to make the menu unique for each entry and also readable.
I am thinking of combining points (1) and (2) in this PR, as they seem quite complementary
In any case, I am almost done with coding (1) and now moving on to (2). Am encountering a small issue
Note that there's no need to tie release cadence and PR cadence here. Even if you think (1) and (2) should be released in the same version, I'd encourage you to open separate PRs. If (1) is basically done, and you're hitting issues addressing (2), I would prefer reviewing and getting (1) merged so I can focus on (2) in isolation. Unless the code is just so inter-related you don't think that'd be valuable. Up to to you.
As per #144, we made downgrade a root-level operation
Oh geeze, I totally forgot this. I'm actually now on the side that a user-level configuration just doesn't make sense and we shouldn't do it. Is there a really compelling use-case for it?
Alternatively, we could drop (2) and (3) altogether and only permit the use of a single root-level configuration file
π
The pitfall there would be cases where users have their own caches with duplicate packages across caches
Can you say more about this? Duplicate packages across multiple caches are still distinct physical packages. So, naively, I would think we want to show them all (as long as which cache it's coming from is visible), and let the user indeed pick a specific one.
As a made-up example, maybe I built some patched version of firefox-1.2.3
into /var/cache/customized
; If I am trying to downgrade I would like to see
1) /var/cache/pacman/firefox-1.2.3
2) /var/cache/customized/firefox-1.2.3
And be able to decide.
This could be addressed by us ... mak[ing] the menu unique for each entry and also readable
We may be saying the same thing here. If so, π again!
Note that there's no need to tie release cadence and PR cadence here. Even if you think (1) and (2) should be released in the same version, I'd encourage you to open separate PRs. If (1) is basically done, and you're hitting issues addressing (2), I would prefer reviewing and getting (1) merged so I can focus on (2) in isolation. Unless the code is just so inter-related you don't think that'd be valuable. Up to to you.
Agree, sorry I get excited and make jumps in my thought process.
Oh geeze, I totally forgot this. I'm actually now on the side that a user-level configuration just doesn't make sense and we shouldn't do it. Is there a really compelling use-case for it?
Yes I had forgotten about that too. The implications of this were clear while trying to code a solution.
We may be saying the same thing here. If so, +1 again!
We are on the same page here, so all good π
Will submit a PR now so you can have a look at what I have so far.
That would also mean we remove the sudo pre-commands within downgrade, particularly for the code segments below. With the removal of sudo in those code chunks, we would need to check root permissions (possibly with id -u) before downgrade is executed and exit if root permissions are not present, similar to calling pacman without root permissions. WDYT?
I have a question/comment on this: let's suppose I am a paranoid guy. Since this is a third-party, unofficial package, I do not trust it too much by default. From this point of view, I am quite nervous running the whole script with root
privileges, and would prefer much more the case where really only pacman
(a package that I trust) is being run as root
.
Was the motivation to assume root
privileges in the whole script "only" to make it easier for implementers, or is there more?
Was the motivation to assume root privileges in the whole script "only" to make it easier for implementers
Yes and no. It's simpler, and I think that helps implementation, UX, and the security-conscious.
Calling EDIT: since we pass URLs directly to sudo
from within the script can lead to poor UX, the password prompt might come at inopportune times. Imagine you kick off downgrade
, it finds some packages, then starts downloading. You're on a slow connection and you know this will take a long time so you go to bed. The next morning you're met with a sudo
prompting you for password. You type it in and it says "timed out". Oops. It's not the worst thing, since the downloads should be there and re-usable if you just rerun downgrade and pick the same versions, but it's something to consider.pacman
(I think), I don't know that this will happen. Let's ignore the scenario for now.
However, from a security perspective: running the script as root is explicit on behalf of the user, it's also simple. If you run a script as normal user and then it calls sudo
somewhere during it's execution, some would find that "sneaky". It could be unclear for which operation it's using sudo
-- how can you be informed enough to answer?
So, I don't think it really harms the paranoia case. Either you trust/audit all of downgrade to know to call it as root, or you... trust/audit all of downgrade to know where/why it's calling sudo
.
That said, I think we could support the security-conscious better. dowgrade
should have a mode where:
- It bypasses the check that you're root
- Does not install packages, only finds them
- Emits their URL-or-path(s) on stdout
Something like,
downgrade --user --print foobar | sudo pacman -S -
Ok, just a comment on this:
However, from a security perspective: running the script as root is explicit on behalf of the user, it's also simple. If you run a script as normal user and then it calls sudo somewhere during it's execution, some would find that "sneaky". It could be unclear for which operation it's using sudo -- how can you be informed enough to answer?
.. but you can still force bash scripts to be run in verbose mode (set -v
or set -x
), so the user is allowed to see when exactly the privilige escalation is needed during the script is being run - and he/she would see that it is sudo pacman ...
that asks for the password.
Fair enough. I would not be surprised if an actually malicious script could get around that, but I guess that's not what you're primarily concerned with?
I am more concerned about unintended damage like accidentally removing or rewriting some files etc. But I am not an expert in the field of root-scripting so I can't say what is the "best practise".