archlinux-downgrade / downgrade

Downgrade packages in Arch Linux

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

  1. I would propose naming the configuration file as downgrade.conf and placing it in ~/.config/downgrade.

  2. 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 within downgrade by replacing the := variable assignment operator with =. The only way to change environmental variables inside downgrade would be via CLI options and/or a configuration file.

  3. 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.

  4. 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?

https://github.com/pbrisbin/downgrade/blob/cef67a42cd5163119dbfc9c6799bebd6b596b918/downgrade#L87-L112

https://github.com/pbrisbin/downgrade/blob/cef67a42cd5163119dbfc9c6799bebd6b596b918/downgrade#L460-L465

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.

commented

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 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. EDIT: since we pass URLs directly to 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:

  1. It bypasses the check that you're root
  2. Does not install packages, only finds them
  3. Emits their URL-or-path(s) on stdout

Something like,

downgrade --user --print foobar | sudo pacman -S -
commented

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?

commented

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".