views:

34

answers:

3

I would like to use a callback feature of an SVN repository (Unfuddle) to ping a URL on my server whenever a commit has been made. I have a PHP script accepting the message and attempting to call a shell script to execute an 'svn update'.

The problem I'm facing is that Apache is running under user 'www-data' and does not have access to the local repository: '.svn/lock' permission denied. I have read all about setting SUID/SGID on shell scripts and how most *NIX OS's simply don't support it because of the security risks involved.

However I can set the SUID/SGID bit on the SVN binary file located at /usr/bin/svn. This alleviates the problem by allowing any user to issue SVN commands on any repository; not the most ideal...

My question is what's the most logical/sane/secure way to implement this type of setup and if I did leave the bits set on the svn binary does that open up a major security risk that I'm failing to realize?

Sorry for the long-winded post; this is my first question and I wanted to be thorough.

Thanks

+1  A: 

There are 2 types of solutions for this kind of problem, polling or event driven.

An example of a polling solution would be to have a cronjob running on your server updating every N minutes. This would probably be the easiest to maintain if it works for you. You would sidestep the whole permissions issue by running the cron from the correct account.

The solution you covered is an event driven solution. They are typically less resource intensive, but can be harder to set up. An another example of an event driven solution would be to have www-data belong to an svn group. Set the SGID bit and chown the repository directory to the svn group. This should allow anyone in that group to check-in/out.

If you need to limit to updating, you can escalate privileges or change user temporarily. You use ssh single purpose keys (aka command keys) to ssh in as the user with the correct privileges. The single purpose key can then be used to do the update.

Another way to escalate privileges would be to use sudo -u [user] [command]. Update the /etc/sudoers file to allow www-data to escalate/change user to one that can perform the update.

Either way I would NOT use SUID/SGID scripts.

dietbuddha
I would prefer the even-driven solution if possible. Your idea to use an 'svn' group follows that of this article: svnbook.red-bean.com/en/1.0/ch06s05.html but as you can see there's a few other things to consider as well which makes it a bit messy. I will need to look further into the 'command keys' option. I guess, for now, my question still remains if setting the SGID for the svn binary itself (not a shell script) has any glaring security issues that I should be aware of. Thank you for your input.
coderich
A: 

As CodeRich already said, you can set up a cron job to frequently update tue working copy(that's also the solution I would use).

Setting svn SUID/SGID is bad, because svn can write files everywhere in the file system (think of a public accessible repository containing a passwd and shadow file, checked out into your /etc). You could use a little suid wrapper program(which is SUID to your user account, not root), which chdir into your working copy and executes svn with the correct parameters there. You can look at ikiwiki which does this when it is used as a cgi.

Another way is to change the permissions of your working copy, so that the www-data user can create and write files there.

Rudi
Thanks Rudi, as a general rule I guess it's best to avoid SUID/SGID on any binaries (especially those owned by root) unless you truly know what's going on. I'll probably end up going with your first suggestion and just CRON it: Maybe have Apache write a file that CRON polls for every minute, if the file exists svn update and remove file. Thanks for your input.
coderich
A: 

change the permissions on your working copy so that Apache can write to it. You have a directory you want to change, you need permissions to do so. Its that simple :)

The problem you then face is allowing any Apache user (or hacked page) to write all over your repo, not a good thing. So - you need to only allow a part of the system to write to it, and the best way to do that is to run your php script as the user who already owns the repo.

That's easily achieved by running the php script as a cgi, or fastcgi process. You can specify the user to use, it doesn't have to be www-data at all, though it does require a bit more setting up, you can have the best of event-driven and security as you're likely to get.

Here's a quick explanation of phpSuexec that does this.

gbjbaanb
I could change the permissions with every repository but it just feels dirty :) I like your idea about having PHP execute as CGI and have the SUID bit set on that script - but my server is not currently set up for that and would require further installations - and well... I'm a minimalist :) I think a simple CRON is the way to go here; although I wonder how shared-hosting accounts manage this because I never had this problem with them. Thanks.
coderich
shared hosts work because PHP was either set up to run as your user, and your home directories were (obviously) owned by your user too. Use phpSuexec (or cgi) and you'll achieve the same result as them. Forget suid bits and suchlike, just run the script as the user that owns the directory you're trying to update. Setting it up is very easy - see the link.
gbjbaanb