dotbot
dotbot copied to clipboard
Add "sudo" option to `link` plugin
Dotbot is used by multiple users — including me — to symlink files in folders that need root
privileges.
It would be nice to add an option (just like path
or create
) to the link
plugin to describe if the target needs to be symlinked with root
privileges. We could name this option sudo
or root
.
For example:
- link:
/etc/some/restricted/path/whatever.conf: whatever.conf
create: true
sudo: true
~/.vimrc: vimrc
sudo: false
Running ./install
would create two symlinks:
-
/etc/some/restricted/path/whatever.conf
created asroot
-
~/.vimrc
created as regular current user
If you prefer to keep Dotbot simple, we could create a plugin that extends the link
plugin.
The idea sounds good! Having a sudo
option on link
seems useful. A couple questions:
- When would the user enter the password?
- Would you be interested in implementing this?
Great!
- When would the user enter the password?
According to the man
pages, sudo
seems to cache the password for 15 minutes by default (at least on the latest Ubuntu LTS):
Security policies may support credential caching to allow the user to run sudo again for a period of time without requiring authentication. The sudoers policy caches credentials for 15 minutes, unless overridden in sudoers(5).
So I think the password should be asked by sudo
itself to let it cache the credentials. So when the user runs ./install
, as soon as Dotbot process a link
with sudo
option enabled, the password prompt appears. Would it be a good UX?
- Would you be interested in implementing this?
Yeah sure. Just to let you know I'm not used to code in Python, but I'm rigorous in my work and I love to learn. I will try my best and will submit a PR.
-
Well, we use Python's
os.symlink()
function to create symlinks. I don't think we want to switch to shelling out tosudo ln -s ...
. I'm not sure what's the recommended way of doing this with Python. -
Ok, sounds great! I can give you feedback on the code 😄 And feel free to ask if you have any questions.
I personally think that shelling out is not a good practice. Likewise running dotbot as a super user or making system config's symbolic links somewhere in the a user's home directory is a terrible idea.
In issue #128 I suggest to mimic the options for the install(1)
command trough copy:
, which sets the file's attributes (access controls). Surely it would be no problem to run an idempotent installer (but you'll have to remember) after editing files yet-to-be copied. The install command also allows for a simple in-place backup to be made (maybe also to clean old backups).
I'll reflect upon this subject, and I'll look around to find out how to achieve this with syscalls and subprocess privileges. (However, I'm not a programmer ...) Please let me hear your thoughts.
+1
I encourage users to manage /etc
with etckeeper, which uses git. It has hooks for common package managers. Make sure to take a look at Automatic push to remote repo on the page I linked. A remote repo could obviously be a thumb drive, a repo on a computer in your LAN or a private repo on the public internet.
Still it would be cool indeed if Dotbot could drop privileges and change file attributes without shelling out.
Using this ugly line now :sob: wish dotbot had sudo support for link.
@ShikherVerma i'd use [ -e /etc/fonts/local.conf ] || sudo ln fontconfig /etc/fonts/local.conf
to make it slightly prettier
I have nothing against adding some kind of sudo
functionality to link
, as long as it's implemented in some reasonable way. Does anyone have good ideas for how to do this?
@anishathalye you are welcome to take inspiration from my dotbot-yum plugin where I implemented a "sudo: true" param - https://gitlab.com/flyingchipmunk/dotbot-yum
edit: ah scratch that just went and looked at link.py, it's using os.symlink(...), not easy to shoehorn sudo in there. Maybe an option for folks is to have a different install_links.conf.yaml with only the link directives and sudo dotbot -c install_links.conf.yaml
That way the security is handled by the os layer instead of managing it in link.py
Ok, does somebody want a separate plugin that will do link with sudo rights? It would add a keyword, say, linksu
and all /etc/
stuff etc should be linked via this plugin.
Most probably there will be a need to shell out though if the password is prompted on Python side and passed via STDIN the whole thing should be more or less secure.
We can even include such functionality in Dotbot core, as long as we have some reasonable way to do it.
I don't think there's too much to worry about security: everything in this scenario is trusted (Dotbot + everything else in your dotfiles).
Also, it's fine to have it start out as a plugin, and if there's interest, we can merge it into core at some point.
Good point! I'll do my best to squeeze out some time to make a pilot version of a plugin. I'll let you know when there will be something.
@anishathalye Can you clarify what the major hurdle is for implementing this functionality into core?
You mention implementing it in a "reasonable" way a couple of times. Can you clarify what that means?
To answer the questions you asked...
1. When would the user enter the password?
Without too much thought here, I would imagine this would happen when the code first encounters a link
target that requires elevated privileges, no?
In 99% of the cases, the user would just have to enter the password one time because, according to the sudo man page...
"[...] the default password prompt timeout for the sudoers security policy is 5 minutes."
which is well beyond the time it would take to execute the entire program (and, if not, the user will just have to enter it a second time if sudo is needed again).
Is there something that I'm missing here that makes this more complicated?
2. Would you be interested in implementing this?
Yep, very much so. Only interested if this goes directly into core though. Not a plugin.
I don't really have a set of rules that I can write down to explain what I mean by "reasonable" implementation. One example of something that I think won't be good enough is shelling out to sudo ln -s
. At the very least, the solution should be robust (no worse error handling than the current version) and cross-platform.
Fair enough. Thanks for chiming back.
Might take a stab at this either this weekend or next if time allows. (unless @ddnomad has already got something together that satisfies those provisions).
@dsifford mine version is just a sketch right now and I do shell out. Thus you definitely can take a stab yourself.
@ddnomad @anishathalye Gonna unfortunately tap out of this one.
Ergonomics are too weird to contribute. I really don't want to install vagrant just to run tests (though, I do appreciate the reason it's being used -- encapsulation).
I still think that simply adding a "sudo" field that accepts a boolean that, when true, runs sudo -u "$USER" ln -s [...]
is totally an acceptable and easy to implement solution.
@dsifford That would need special configuration for windows users though as people might use dotbot for non-unix/linux OS'.
@SirWindfield Why would windows users even use the sudo
option?
No idea, aren't there protected directories too? o.O
Anyway, I just had a small idea. Maybe link each normal file first and after that, re-run the script (automatically) passing it a flag like sudo=true
. Dotbot would then only link all files that are declared as sudo. Youd could even change the owner of the files to the sudo caller by using SUDO_UID
and SUDO_GID
environment variables and calling os.chown
. It would basically be a two step process.
Just came across this issue, this is something I've been looking for ever since I've started using dotbot
back in 2015!
Definitely keeping an eye on this one!
Isn't this a security issue? Linking a system file to a user-writable target would let any process running as that user change the file, which kind of defeats the purpose of having system files in the first place. For some files (e.g. systemd unit overrides) this would effectively allow the user to run arbitrary processes at root, without even noticing.
Personally I use shell
to install system files, e.g.
- shell:
- command: sudo -n install -D -m644 systemd/timesyncd.conf /etc/systemd/timesyncd.conf
stderr: true
sudo -n
makes sudo fail if it would have to prompt for password, so that ./install
runs without stopping at any prompts even if I have no active sudo ticket. To install system files I use sudo -v && ./install
which acquires a sudo ticket before installing my dotfiles.
I actually want those systemd overrides. In this case, one would also need to ProtectHome=no
- so at least you know you're doing something that comes with some risk.
Using shell
works, but then you kind of lose the niceness of the yaml config. I found custom install scripts on the wiki and I've created install.sudo.conf.yaml
and an install-sudo
script. I think this is a good compromise.
I used to ./install
and immediately follow it with sudo ./install
- but that would put a bunch of symlinks in root's directory, which was obviously not preferable. Now I have shell
with sudo ./install-sudo
in it, so ./install
can take care of all of it, with nothing irrelevant going to root's directory.
any news on this?
I think the install-sudo
script is an alright enough way to go. That allows things to stay separate if need be.
See these files: install-sudo, install.sudo.conf.yaml, and install.conf.yaml
Yeah, I think that's the recommended approach, at a high level. Have two separate .conf.yaml
files, and call Dotbot on each, once without sudo, and the other time with sudo.
You could use variations of that, e.g. having an install.conf.yaml
and a sudo.conf.yaml
, and then having your ./install
script itself be modified to call Dotbot on each of those (I think I would do that rather than putting a shell:
line in the install.conf.yaml
).
I honestly didn't even thinking about having the install
script call sudo.conf.yaml
!
Hi, I also had the problem, that i needed to execute parts of my install.con.yaml as root. So I write a plugin for this purpose. Maybe this could help you too: dotbot-sudo Please let me know what you think :)
You could add it to the plugins list for extra visibility.
Added some plugins to the plugin list :)
I know this is really outdated, but the new install scripts solve this problem by allowing you to add -sudo
to the end of any configuration. i.e. ./install-standalone some-config other-config-sudo
. Only downside is that it requires you to have implemented the more advanced setup from the Tips and Tricks section of the wiki.