Let users execute commands as other users without typing a password (sudo)

It’s been almost a year since I discovered the joys of SVN post-commit hooks (I started by following this excellent and concise guide), but I never really gave it the time it wanted: now that I have, my scripts finally work flawlessly and I’m very happy with the result!

One of the things I’ve done is to monitor only some specific folders in my SVN repository, folders that contain files that I want to copy to another folder that is monitored using inotify (I have a server Java application that inspects these files and decides whether they’re “accepted” to be served to clients.. I plan to switch to Java 7 to test the new java.nio.file package, but for now I use a little inotify bash script).

I needed a working copy of the SVN repository (well, just a branch actually), and I needed it to be updated whenever a file in one of the monitored folders is edited, added or deleted. So, I created a user called svnuser that just pulls updates whenever the post-commit hook tells it to. At first I thought of named pipes as a means to have the two processes communicate: a daemon script always running in background launched by svnuser waiting for notifications on a named pipe that are written by the post-commit hook; it seemed to work fine, but then I thought “wouldn’t it be easier if this script was launched by the post-commit hook itself?”.

It is 🙂

Post-commit hooks are executed by the user that is committing changes, so I had to use sudo. To configure sudo, type visudo (or, equivalently, vim /etc/sudoers as user root.. just remember to save the file using :wq! to override the read-only setting).

In the User privilege specification section you should see this line

root    ALL=(ALL) ALL

that means that user root can run any command (last ALL) on any host (first ALL) as any user (the ALL between parentheses).

You can add your definitions at the very bottom of the file (they’re executed in order, so you can override a definition with a more specific one just by putting the overriding definition after the overridden).
You can use groups, too! Just put a % symbol in front of the group name.
You can also apply a rule to a single command, or to a (comma-separated) list of commands by replacing the last ALL.
You can do a lot of stuff, actually, if you’re interested just dive into this page. I had to spend some time to figure out what I needed to do, so I hope that a little summary will help somebody.

I don’t want to force users to type their passwords every time that they commit some file to one of the “sensible” paths, so I included the NOPASSWD option.

Here’s the final line:

%svngroup ALL=(svnuser) NOPASSWD: /home/svnuser/svnsync *

that means that any user in the group named svngroup can run the /home/svnuser/svnsync script as user svnuser passing whatever parameter (last *) and without having to input their sudo password (NOPASSWD).

That’s it, now my post-commit hook just calls the svnsync like this:

sudo -u svnuser /home/svnuser/svnsync $UPDATED_PATH