Showing posts with label configuration management. Show all posts
Showing posts with label configuration management. Show all posts

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.

Wednesday, December 2, 2009

rcs

The first thing I was taught on my first day as a system administrator was to always do a backup of the files I wanted to modify. The way I was told was this one :
cp foo foo.20091202
(the extension is year - month - day)

This proved to be a poor way to backup files and it has a lot of drawbacks. Now, I usually use RCS to do this job. It gives you most of the advantages of a revision control system like CVS or subversion but without the burden to install lot of binaries, libraries and create global repositories (of course, with rcs you don't have the concurrent access feature nor authentication stuff but we don't really care about that just to backup some configuration files).

In Debian, you can install it like this :
apt-get install rcs
If you have Redhat, it would be :
yum install rcs

Then, to backup a file in the current directory :
mkdir RCS
ci -l foo
("-l" option is for the lock feature of rcs, something that does not seem very usefull to my view).

After some changes in the file, you can see them with rcsdiff :
rcsdiff foo
To save a new version of the file :
ci -l foo
If you want to list all the versions of your file :
rlog foo
To check the differences between version 3 and version 5 :
rcsdiff -r3 -r5 foo
And finally, if you want to get version 4 back :
co -r4 foo

One thing I do appreciate by using rcs to modify every configuration file, is that it is very easy to know all the changes you've made on your server (for instance, if you have to migrate the server to a new OS it may be helpfull) by typing :
locate RCS

Of course, this will never sustitute a real remote backup policy (with TSM or Netbackup for instance) of your server. But it is much more flexible to know what was changed in a file with RCS than looking your modified versions on the tapes...

Keep in mind that RCS is for local changes. If you want to do the same modification on a file on all your servers, maybe you should pass to a CVS/subversion system, or use a different method to centralize your changes.