SVN

From Unix Wiki
Jump to: navigation, search

About

Following configs and scripts will help one to configure SUBVERSION and restrict permissions between users in LDAP.

Configs

Sample configuration files.

SVN + LDAP + WEBSVN

# cat /etc/httpd/conf.d/subversion.conf
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

WebSVN + LDAP auth config

# cat /etc/httpd/conf.d/websvn.conf 
Alias /websvn /var/www/websvn

  <Directory /var/www/websvn>
  AuthName "WebSVN"
  AuthType Basic
  AuthBasicProvider ldap
  Require valid-user
  AuthzLDAPAuthoritative on
  AuthLDAPGroupAttribute memberUid
  AuthLDAPGroupAttributeIsDN off
  AuthLDAPURL ldap://ldap.company.lan/dc=company,dc=lan?uid?
  DirectoryIndex index.php
  Options FollowSymLinks
  Order allow,deny
  Allow from all
  <IfModule mod_php4.c>
  php_flag magic_quotes_gpc Off
  php_flag track_vars On
  </IfModule>
  </Directory>

WebSVN config.php

# grep -v "^/" /var/www/websvn/include/config.php | egrep -v "^$"
<?php
$config->setTrustServerCert();
$config->parentPath('/var/www/svn/');
$config->addTemplatePath($locwebsvnreal.'/templates/calm/');
$config->addTemplatePath($locwebsvnreal.'/templates/BlueGrey/');
$config->addTemplatePath($locwebsvnreal.'/templates/Elegant/');
$config->useAuthenticationFile('/var/www/svn/svnaccess.conf'); // Global access file
$config->addInlineMimeType('text/plain');
$config->allowDownload();
$config->setMinDownloadLevel(2);
$config->useEnscript();
$config->useGeshi();
set_time_limit(0);
$config->expandTabsBy(8);

Script for creating svnaccess file for WebSVN

#!/usr/bin/perl
=head
    Script for parsing ldapsearch output
=cut

use strict;
use warnings;
use Switch;

# Configuration variables. Adjust accordingly.
my $ldap_basedn = "dc=company,dc=lan";
my $ldap_groupname_prefix = "svn-*";
my $ldap_filter = "(&(objectclass=posixgroup)(cn=$ldap_groupname_prefix))";
my $ldap_uri = "ldap://ldap.company.lan";

# Main variables
my %repos;
my $newrepo = 0;
my $repo;grep -v "^/" /var/www/websvn/include/config.php | egrep -v "^$"
<?php
$config->setTrustServerCert();
$config->parentPath('/var/www/svn/');
$config->addTemplatePath($locwebsvnreal.'/templates/calm/');
$config->addTemplatePath($locwebsvnreal.'/templates/BlueGrey/');
$config->addTemplatePath($locwebsvnreal.'/templates/Elegant/');
$config->useAuthenticationFile('/var/www/svn/svnaccess.conf'); // Global access file
$config->addInlineMimeType('text/plain');
$config->allowDownload();
$config->setMinDownloadLevel(2);
$config->useEnscript();
$config->useGeshi();
set_time_limit(0);
$config->expandTabsBy(8);

my @users;

# Get raw data
my @output = `ldapsearch -H $ldap_uri -b $ldap_basedn -u -x -LLL "$ldap_filter" cn memberUid`;

# Fill hash with data collected so far
sub fill {
  foreach (@users) {
    $repos{"$repo"}->{"$_"}='';
  }
  @users=();
  $repo='';
}

# Collecting access file data
foreach my $line (@output) {
#  print $line, "\n";
  chomp $line;
  switch ($line) {
    case /^ufn:/         { if ( $newrepo ) { fill } $newrepo = 1; }
    case /^cn:/          { $line =~ m|^cn: svn-(\S+?)-r.$|; $repo = $1; }
    case /^memberUid:/   { $line =~ m|^memberUid: (\S+?)$|; push (@users, $1) }
  }
}
fill;

# Printing access file
foreach $repo (keys %repos) {
  print "[$repo:/]\n";
  foreach my $user (keys %{ $repos{"$repo"}}) {
    print "$user = r\n";
  }
  print "\n";
}

exit 0

addrepo.sh script

# cat addrepo.sh 
#!/bin/bash

# Variables
version="0.1"
author="Mikhail Shevtsov"
repo=$1
apache_confd="/etc/httpd/conf.d"
ldap_basedn="dc=company,dc=lan"
ldap_uri="ldap://ldap.company.lan/"
svn_parent_path="/var/www/svn"
owner_group="apache:apache"
error=0

# Next function will print usage information
function usage {
  error=0
  echo "$0 script version: ${version}, author: ${author}

Usage: $0 <REPO_NAME>

  This particular script will create new svn repository.
Script is expecting repository name as first argument.
Script will fail in following cases:
  1. File exists: ${apache_confd}/svn.<REPO_NAME>.conf;
  2. Repo dir exists: ${svn_parent_path}/<REPO_NAME>;
  3. LDAP groups exist: svn-<REPO_NAME>-ro or svn-<REPO_NAME>-rw."
  exit ${error} 
}

# Next function will check if repository conf file already exist
function check_conf {
  if [ -e ${apache_confd}/svn.${repo}.conf ]; then
    echo "ERROR:  File exists: ${apache_confd}/svn.${repo}.conf"
    error=1
  fi
}

# Next function will check if repository dir already exist
function check_repo_dir {
  if [ -d ${svn_parent_path}/${repo} ]; then
    echo "ERROR:  Repository directory exist: ${svn_parent_path}/${repo}"
    error=1
  fi
}

# Next function will check if ldap groups already exist
function check_ldap {
  ldap_filter="(&(objectClass=posixGroup)(cn=svn-${repo}-rw))"
  if [ ! -z "`ldapsearch -H ${ldap_uri} -b ${ldap_basedn} -u -x -LLL "${ldap_filter}"`" ]; then
    echo "ERROR:  LDAP group exist: svn-${repo}-rw"
    error=1
  fi
  ldap_filter="(&(objectClass=posixGroup)(cn=svn-${repo}-ro))"
  if [ ! -z "`ldapsearch -H ${ldap_uri} -b ${ldap_basedn} -u -x -LLL "${ldap_filter}"`" ]; then
    echo "ERROR:  LDAP group exist: svn-${repo}-ro"
    error=1
  fi
}

# Next function will generate apache svn conf file
function create_conf {
  echo "<Location /${repo}>
  DAV svn
  SVNPath ${svn_parent_path}/${repo}
  AuthType Basic
  AuthBasicProvider ldap
  Require valid-user
  AuthName 'SVN LDAP Auth'
  AuthzLDAPAuthoritative on
  AuthLDAPGroupAttribute memberUid
  AuthLDAPGroupAttributeIsDN off
  AuthLDAPURL ${ldap_uri}${ldap_basedn}?uid?
  <LimitExcept MERGE MKCOL POST PUT DELETE PATCH PROPPATCH>
    Require ldap-group cn=svn-${repo}-ro,ou=groups,${ldap_basedn}
    Require ldap-group cn=svn-${repo}-rw,ou=groups,${ldap_basedn}
  </LimitExcept>
  <Limit MERGE MKCOL POST PUT DELETE PATCH PROPPATCH>
    Require ldap-group cn=svn-${repo}-rw,ou=groups,${ldap_basedn}
  </Limit>
</Location>" > ${apache_confd}/svn.${repo}.conf
  echo "Configuration file was created: ${apache_confd}/svn.${repo}.conf"
}

# Next function will create svn repository on disk
function create_repo {
  svnadmin create ${svn_parent_path}/${repo}
  chown -R ${owner_group} ${svn_parent_path}/${repo}
  echo "SVN repository was created: ${svn_parent_path}/${repo}"
}

# Next function will add two new ldap groups
function add_ldap_groups {
  ldap_filter="(&(objectClass=posixGroup)(cn=svn-*))"
  ro_gid=$((`ldapsearch -H ${ldap_uri} -b ${ldap_basedn} -u -x -LLL "${ldap_filter}" cn gidNumber | grep gidNumber | sort | tail -n 1 | awk '{print $2}'`+1))
  rw_gid=$((${ro_gid}+1))
  ldapadd -H ${ldap_uri} -W -D "cn=root,${ldap_basedn}" << EOF
dn: cn=svn-${repo}-ro,ou=groups,${ldap_basedn}
objectClass: top
objectClass: posixGroup
cn: svn-${repo}-ro
gidNumber: ${ro_gid}
memberUid:

dn: cn=svn-${repo}-rw,ou=groups,${ldap_basedn}
objectClass: top
objectClass: posixGroup
cn: svn-${repo}-rw
gidNumber: ${rw_gid}
memberUid:

EOF
  echo "LDAP groups were added: svn-${repo}-ro (gid: ${ro_gid}), svn-${repo}-rw (gid: ${rw_gid})"
}
# Checking prereqs
if [ -z ${repo} ]; then usage
fi

check_conf
check_repo_dir
check_ldap

if [ ${error} -ne 0 ]; then exit ${error}
fi


# Creating repository
add_ldap_groups
create_conf
create_repo

echo "
  Repository '${repo}' was successfully created.
Please manually restart apache server:

service httpd restart"

exit 0