Scott
Scott

Reputation: 6736

Avoid having subversion modify Linux file permissions.

All of my code base is being stored in a subversion repository that I disperse amongst my load balanced Apache web servers, making it easy to check out code, run updates, and seamlessly get my code in development onto production.

One of the inconveniences that I'm sure there is a easy work around for (other than executing a script upon every checkout), is getting the Linux permissions set (back) on files that are updated or checked out with subversion. Our security team has it set that the Owner and Group set in the httpd.conf files, and all directories within the documentRoot receive permissions of 700, all non-executable files (e.g. *.php, *.smarty, *.png) receive Linux permissions of 600, all executable files receive 700 (e.g. *.sh, *.pl, *.py). All files must have owner and group set to apache:apache in order to be read by the httpd service since only the file owner is set to have access via the permissions.

Every time I run an svn update, or svn co, even though the files may not be created (i.e. svn update), I'm finding that the ownership of the files is getting set to the account that is running the svn commands, and often times, the file permissions are getting set to something other than what they were originally (i.e. a .htm file before an update is 600, but after and svn update, it gets set to 755, or even 777).

What is the easiest way to bypass subversion's attempts at updating the file permissions and ownership? Is there something that can be done within the svn client, or on the Linux server to retain the original file permissions? I'm running RHEL5 (and now 6 on a few select instances).

Upvotes: 32

Views: 24591

Answers (6)

Bell
Bell

Reputation: 455

You can solve this. Use setgid.

  1. You have apache:apache running the server

  2. Set group permission on all files and directories. The server will read files by it's group

  3. Set setgid on all directories - only on directories: setting this on files has a different function

    Example ('2' is setgid):

    chmod 2750

  4. Make apache the group of all directories

What happens is

  • New files and directories created by any account will be owned by the apache group

  • New directories will inherit the setgid and thus preserve the structure without any effort

See https://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories

Upvotes: 2

Ilya Bystrov
Ilya Bystrov

Reputation: 3056

I also had a similar problem. I found a cool script: asvn (Archive SVN).

You can download it here: https://svn.apache.org/repos/asf/subversion/trunk/contrib/client-side/asvn

Description:
Archive SVN (asvn) will allow the recording of file types not
normally handled by svn. Currently this includes devices,
symlinks and file ownership/permissions.

Every file and directory has a 'file:permissions' property set and
every directory has a 'dir:devices' and 'dir:symlinks' for
recording the extra information.

Run this script instead of svn with the normal svn arguments.

This blog entry (which helps me to find script) http://jon.netdork.net/2010/06/28/configuration-management-part-ii-setting-up-svn/ shows a simple usage.

Upvotes: 1

Gerben Versluis
Gerben Versluis

Reputation: 566

I wrote a small script that stores permissions and owner, executes your SVN command and restores permissions and owner. It is probably is not hackerproof but for private use it does the job.

svnupdate.sh:

#!/usr/bin/env bash
if [ $# -eq 0 ]; then
    echo "Syntax: $0 <filename>"
    exit
fi

IGNORENEXT=0
COMMANDS=''
FILES='';
for FILENAME in "$@"
do
    if [[ $IGNORENEXT > 0 ]]; then
        IGNORENEXT=0
    else
        case $FILENAME in
            # global, shift argument if needed
            --username|--password|--config-dir|--config-option)
            IGNORENEXT=1
            ;;
            --no-auth-cache|--non-interactive|--trust-server-cert)
            ;;
            # update arguments, shift argument if needed
            -r|--revision|--depth|--set-depth|--diff3-cmd|--changelist|--editor-cmd|--accept)
            IGNORENEXT=1
            ;;
            -N|--non-recursive|-q|--quiet|--force|--ignore-externals)
            ;;
            *)
            if [ -f $FILENAME ]; then
                FILES="$FILES $FILENAME"
                OLDPERM=$(stat -c%a $FILENAME)
                OLDOWNER=$(stat -c%U $FILENAME)
                OLDGROUP=$(stat -c%G $FILENAME)
                FILECOMMANDS="chmod $OLDPERM $FILENAME; chown $OLDOWNER.$OLDGROUP $FILENAME;"
                COMMANDS="$COMMANDS $FILECOMMANDS"
                echo "COMMANDS: $FILECOMMANDS"
            else
                echo "File not found: $FILENAME"
            fi
            ;;
        esac
    fi
done
OUTPUT=$(svn update "$@")
echo "$OUTPUT"
if [[ ( $? -eq 0 ) && ( $OUTPUT != Skipped* ) && ( $OUTPUT != "At revision"* ) ]]; then
    bash -c "$COMMANDS"
    ls -l $FILES
fi

Upvotes: 1

ACK_stoverflow
ACK_stoverflow

Reputation: 3305

One thing you may consider doing is installing the svn binary outside your path, and putting a replacement script (at and called /usr/bin/svn, or whatever) in the path. The script would look something like this:

#!/bin/sh

# set umask, whatever else you need to do before svn commands

/opt/svn/svn $* # pass all arguments to the actual svn binary, stored outside the PATH

# run chmod, whatever else you need to do after svn commands

A definite downside is that you'll probably have to do some amount of parsing of the arguments passed to svn, i.e. so you can pass the same path to your chmod, not run chmod for most svn commands, etc.

There are also probably some security considerations here. I don't know what your deployment environment is like, but you should probably investigate that a bit further.

Upvotes: 1

Anya Shenanigans
Anya Shenanigans

Reputation: 94584

the owner of the files will be set to the user that is running the svn command because of how it implements the underlying up command - it removes and replaces files that are updated, which will cause the ownership to 'change' to the relevant user. The only way to prevent this is to actually perform the svn up as the user that the files are supposed to be owned as. If you want to ensure that they're owned by a particular user, then run the command as that user.

With regards to the permissions, svn is only obeying the umask settings of the account - it's probably something like 066 - in order to ensure that the file is inaccessible to group and other accounts, you need to issue 'umask 077' before performing the svn up, this ensures that the files are only accessible to the user account issuing the command.

I'd pay attention to the security issue of deploying the subversion data into the web server unless the .svn directories are secured.

Upvotes: 18

thomson_matt
thomson_matt

Reputation: 7691

You can store properties on a file in Subversion (see http://svnbook.red-bean.com/en/1.0/ch07s02.html). You're particularly interested in the svn:executable property, which will make sure that the executable permission is stored.

There's no general way to do this for all permissions, though. Subversion doesn't store ownership either - it assumes that, if you check something out, you own it.

Upvotes: 9

Related Questions