Sunday, April 4, 2010

permissions in websvn

Subversion is a great tool for developers but it can also be very useful to centralize your changes of the configuration files or the scripts you deploy on your servers. To make it easier to use (in a read only way...), you can install websvn, that is a web front-end to your subversion repositories.
This little howto aims to explain how to install a websvn server (the web server for subversion repositories) in such way that we can easily enforce user permissions. To achieve it, we will use an apache/ldap authentication and we will hack a bit the websvn code to be able to use the same access rights file in subversion and in websvn and to fix a bug that appears when you have the same repository name in two different parent paths.
This howto works here with a Redhat 5 server and the client used is a Debian 5 desktop.

To explain the permission feature and show that the bug is fixed, I will create 2 parent path directories, each one containing 3 subversion repositories :
  • python, with repositories : dns, databases and network
  • java, with repositories : web1, web2 and dns
First, let's start installing subversion and apache. Since you can find many howto on the internet doing this, I won't give a lot of explanations about this part. If you just copy-paste the following commands, just remember to change the LDAP server, user and password in the /etc/httpd/conf.d/ldapConfiguration.included file and insert your LDAP user in the /etc/subversion/svn-acl* files.
yum install subversion httpd mod_dav_svn
mkdir -pv /opt/subversion/{python,java}
svnadmin create /opt/subversion/python/dns
svnadmin create /opt/subversion/python/databases
svnadmin create /opt/subversion/python/network
svnadmin create /opt/subversion/java/web1
svnadmin create /opt/subversion/java/web2
svnadmin create /opt/subversion/java/dns

cat >> /etc/httpd/conf.d/subversion.conf <<-EOF
<Location /python>
Include /etc/httpd/conf.d/ldapConfiguration.included

SVNParentPath /opt/subversion/python
AuthzSVNAccessFile /etc/subversion/svn-acl-python.conf
</Location>

<Location /java>
Include /etc/httpd/conf.d/ldapConfiguration.included

SVNParentPath /opt/subversion/java
AuthzSVNAccessFile /etc/subversion/svn-acl-java.conf
</Location>
EOF

cat > /etc/httpd/conf.d/ldapConfiguration.included <<-EOF
DAV svn

AuthBasicProvider ldap
AuthzLDAPAuthoritative off
AuthLDAPURL ldap://ldapserver.example.org/dc=example,dc=org?uid
AuthLDAPBindDN uid=readerall,ou=special,ou=users,dc=example,dc=org
AuthLDAPBindPassword passwordToChange

AuthType Basic
AuthName "Subversion control"
Require valid-user
EOF

cat > /etc/subversion/svn-acl-python.conf <<-EOF
# These ACLs are for http method of subversion
# You don''t need to reload apache to get the permissions enforced. Just modify the file and save it.

[groups]
pythondev = smith,mike,robert

[dns:/]
# everybody can read this repository
* = r
@pythondev = rw

[databases:/]
mike = rw

[network:/]
@pythondev = rw
EOF

cat > /etc/subversion/svn-acl-java.conf <<-EOF
[groups]
javadev = mike,sarah,arthur,elen

[web1:/]
@javadev = rw

[web2:/]
daniel = r
@javadev = rw

[dns:/]
@javadev = rw
EOF

rm -f /etc/httpd/conf.d/authz_ldap.conf
chown -R apache /opt/subversion/

chkconfig httpd on
service httpd start
Now that subversion is installed and configured, you can do some tests on your computer :
apt-get install subversion
svn --username mike checkout http://subversionserver/python/dns
cd dns
echo world > hello
svn add hello
svn ci hello

OK, subversion seems to work fine! So let's install websvn now.
Download the last tar.gz version from the project website and place this archive to the /tmp directory of your subversion server.
cd /tmp
tar xvfz websvn*tar.gz
rm -f websvn*tar.gz
cd websvn*
mkdir -pv /opt/websvn/prod
mv * /opt/websvn/prod/

cat > /etc/httpd/conf.d/websvn.conf <<-EOF
Alias /websvn /opt/websvn/prod/
<Directory /opt/websvn/prod/>
Options MultiViews
DirectoryIndex wsvn.php

AuthBasicProvider ldap
AuthzLDAPAuthoritative off
AuthLDAPURL ldap://ldapserver.example.org/dc=example,dc=org?uid
AuthLDAPBindDN uid=readerall,ou=special,ou=users,dc=example,dc=org
AuthLDAPBindPassword passwordToChange

AuthType Basic
AuthName "Subversion control"
Require valid-user
</Directory>
EOF
Remember to change the previous file with your ldap credentials.
Now we will apply some patches on websvn. The files I have changed work with the webSvn 2.3.0.
In order to help you to apply the patches on another version, I will both give you the file and my RCS file (the first version of RCS being the official one).

The first file you should change is the template /opt/websvn/prod/templates/calm/header.tmpl that shows a bug when you are looking at the root web page (download the normal version / the RCS version).

Second file is more important. It is a PHP library : /opt/websvn/prod/include/configclass.php. My version of this file fixes the bug I mentioned before : if you have two repositories with the same name in different parentPath, the uncorrected webSvn will only show one of them. In our current example, that would mean you would only see python/dns, not java/dns. What is more, my version adds the useAuthenticationFileGroup function that lets you define permissions at the parentPath level (php is far from being my favorite script language so please forgive me if my code is not perfect...). I will explained it in a few lines. You may download the text version here and the RCS version here.

Now, we shall edit the webSvn main configuration file. Start with copying the sample file :
cp /opt/websvn/prod/include/distconfig.php /opt/websvn/prod/include/config.php
Then edit the copy you made.
First, add the two parentPaths : those are the directories that contain the subversion repositories you create at the beginning of this howto.
$config->parentPath('/opt/subversion/python','python');
$config->parentPath('/opt/subversion/java','java');
Then we only activate the template we fixed :
$config->addTemplatePath($locwebsvnreal.'/templates/calm/');
//$config->addTemplatePath($locwebsvnreal.'/templates/BlueGrey/');
//$config->addTemplatePath($locwebsvnreal.'/templates/Elegant/');
Other important configuration lines are :
$config->useTreeIndex(true); // Tree index, open by default
...
$config->useMultiViews();
Finally, we must link the parentPaths with the permission files we wrote before :
$config->useAuthenticationFileGroup('/etc/subversion/svn-acl-python.conf','python');
$config->useAuthenticationFileGroup('/etc/subversion/svn-acl-java.conf','java');
Here you can see the function I wrote in the patched library file. If you don't use this function, you would have to use the standard useAuthenticationFile function. That would mean, writing 6 lines instead of 2 and remembering to change this configuration every time you create or delete a repository.

The webSvn installation ends like that :
yum install php-pear
ln -s /opt/websvn/prod/templates /var/www/html
service httpd reload
Finally, just type the http://subversionserver/websvn URL in a brother to check that everything is OK.

1 comment:

  1. Thank you very much for this article! I had exactly the same problem and solved it first very hacky. Your solution is cleaner and works like a charm.
    It seems the websvn people do not need multiple parent paths, which is a very common scenario I think.

    ReplyDelete