moonwatcher.it

Gianluca Riccardi's minimalist weblog

Home About

HTTPS access to SVN repositories


Introduction

It's possibile to configure an HTTPS access to Subversion repositories, using a webserver like Apache2.2, with WebDAV functionalities provided by the DAV apache modules. The SSL connection provides a secure tunnel and users will authenticate against a OpenLDAP directory service authenticating only users pertaining to a allowed group.

Structure

The HTTPS will be made available by a front-end web server, Nginx, HTTP reverse-proxying to Apache2 on port 80, that will take care of users authetication and authorization, accessing the subversion repositories. The Apache2.2 virtual host will be running as a system user owning the repositories and thus having the needed read and write permissions.

Nginx will be listening on the public IP interface on port 443 (or another port of choice) making the SSL connection using self signed certificate and key. Apache2.2 can be installed on the same machine and listening on the loopback, or can be installed on another virtual or physical machine in a private IP network, listening on port 80. Having the back-end server on a private network is a choice of network design, it can be varied on particular needings as well, but it will be the only one discussed here.

The operating system of choice is GNU/Linux, having a SLES10.3 SP1 running on the front-end machine and a Ubuntu 8.10 server edition on the back-end server.

Contents

  1. Nginx, compilation and installation
  2. OpenSSL certificate and key generation
  3. Installing SSL key and certificate in Nginx
  4. Apache2.2 installation and configuration
  5. Nginx, HTTPS reverse-proxying to apache2
  6. Apache2, configuring the LDAP authentication
  7. Apache2, configuring the SVN DAV modules and access
  8. Subversion, creating and migrating repositories

1. Nginx, compilation and installation

In the Nginx compilation and installation wiki page there's thorough documentation giving details on the process, here will be showed an example of how to compile with the required SSL module, so get in the /usr/local/ directory and download the sources tar.gz package:

wget http://sysoev.ru/nginx/nginx-0.6.32.tar.gz

and unpack it:

tar -xzf nginx-0.6.32.tar.gz

before running the configure script it can be useful to check for latest updates to the configuration process:

./configure --help

get in the source directory and run the configure script:

./configure --with-http_ssl_module

and then compile:

make

make install

the contents of the sources dir should be as follows:

1
2
3
4
5
6
7
        client_body_temp/
        conf/
        fastcgi_temp/
        html/
        logs/
        proxy_temp/
        sbin/

having the nginx binary in the sbin/ directory.

1.2 Nginx configuration and test

An init script is needed in order to manage the sevice and correctly boot-up:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#! /bin/sh
### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the nginx web server
# Description:       starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sbin/nginx
NAME=nginx
DESC=nginx

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then

    . /etc/default/nginx

fi

set -e

case "$1" in
start)
    echo -n "Starting $DESC: "
    start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS
    echo "$NAME."
    ;;

stop)
    echo -n "Stopping $DESC: "
    start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid
    echo "$NAME."
    ;;

restart|force-reload)
    echo -n "Restarting $DESC: "
    start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON
    sleep 1    
    start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS    
    echo "$NAME."    
    ;;

reload)    
        echo -n "Reloading $DESC configuration: "    
        start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/nginx.pid \
            --exec $DAEMON    
        echo "$NAME."    
        ;;

*)
    N=/etc/init.d/$NAME
    echo "Usage: $N {start|stop|restart|force-reload}" >&2
    exit 1
    ;;

esac

exit 0

edit it as needed then copy the above script in the /etc/init.d/ directory and add it to the default runlevels using chkconfig command:

`chkconfig --add /etc/init.d/nginx

` as a facility, create the symlink to the boot script in the SLES style:

`ln -s /etc/init.d/nginx /usr/sbin/rcnginx

` before starting the Nginx web server, a minimum configuration of the main nginx.conf file is needed, giving the webserver a name through the server_name directive; if a DNS hostname is not yet available, it's possibile to configure a static route (fake host in the /etc/hosts file in the local desktop computer in the case of unix based OSes) just for testing/learning before releasing, and make sure the listen directive is, for now, with value 80 and then, as root,

start the server:

`root# rcnginx start

` and using a web-browser verify that a 200 http response is received, usually displaying the default static page.

2. OpenSSL certificate and key generation

A private key and certificate for the nginx server are needed in order to make the SSL connection possible, in this a self signed-certificate will be created and used, it's assumed that a OpenSSL installation is already available in the running SLES10.

Generating the key:

`root# openssl genrsa -out privkey 1024

` generating the certificate request:

`root# openssl req -new -key privkey -out signing_request

` note: a few params will be requested, the most important is the 'Common Name' which has to be the server name otherwise the certificate will not be accepted, having the nginx unable to initiate the SSL connection itself.

generating the self-signed certificate:

`root# openssl x509 -req -days -in signing_request -signkey privkey -out server_certificate

` issuing the last opennsl command will generate the certificate to be configured in the nginx server, for a deeper and complete OpenSSL documentation refer to the local installation Docs and/or make a websearch.

3. Installing SSL key and certificate in Nginx

3.1 Confgiuring Nginx

In order to have Nginx correctly initiate and establish a HTTPS connection, the generated certificate file and key must be installed.

The Virtual Hosts configuration will be kept in separate files and location than the nginx.conf, in a directory contained under the conf/ dir of the Nginx installation:

1
2
3
        /usr/local/nginx/conf/sites-available

        /usr/local/nginx/conf/sites-enabled

as can be noted the Debian style won. In the sites-available directory will be put the Virtual Host files holding the host specific configurations, while in the sites-enabled will be put the symlinks pointing to the hosts wanted to be live. In the nginx.conf main configuration file will be specified the directive to include the sites-enabled contents, as following:

1
2
3
        # Virtual hosts a la Debian

        include sites-enabled/*;

in the sites-available directory, copy a file as the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
            server {

                listen       443;

                server_name  hostname.domain;

                ssl on;

                ssl_certificate     /etc/ssl/certs/server_certificate;

                ssl_certificate_key /etc/ssl/certs/privkey;

                access_log  logs/hostname.domain_access.log;

                error_log   logs/hostname.domain_error.log;

                location / {

                    root   html;

                    index  index.html index.htm;

                    # proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

                    # proxy_set_header   Host $http_host;

                    # proxy_pass         http://IP_Addr;

                    # proxy_redirect     off;

                    set $dest $http_destination;

                    if ($http_destination ~ "^https://(.+)") {

                        set $dest http://$1;

                    }

                }

            }

by reading the ssl_certificate and ssl_certificate_key directives values, the locations of certificate file and key can be found, after editing the configuration file, symlink this file from the sites-enabled directory to make them included and restart the nginx server.

After restarting nginx, open a https connection in the web-browser and verify the SSL connection working without errors.

The Nginx configuration can be considerd complete and working, later on nginx will be configured to reverse-proxy to apache2.

4. Apache2.2 installation and configuration

4.1 Installing Apache2 mpm-ITK

In order to have every Virtual Host running under a separate user, apache2 mpm-itk will be installed on the Ubuntu back-end server:

`root# aptitude install apache2-mpm-itk

`

4.2 configuring the base Virtual Host

On the machine hosting the central repositories, there will be the need to create and administer the subversion repositories themselves, for this reason a special user, dedicated to the purpose, will be created:

1
2
3
            root# addgroup --system scm-local

            root# adduser --system --home /path/to/repos -g scm-local scm

in this way, the directory trees starting from the scm home dir will have a coherent permissions scheme, and the scm user will be the user the VirtualHost will be running as. The group is named scm-local because there is a already created and populated LDAP group named scm.

The basic apache2 virtual host configuration will be similar to:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    <VirtualHost IP_addr:80>

        ServerName hostname.dominio

        ErrorLog /path/to/logs/scm_error

        CustomLog /path/to/logs/scm_access combined

        # assign the scm user to this VH

        AssignUserID scm scm-local

        # only needed for testing

        DocumentRoot /scm/home/dir

    </VirtualHost>

after testing the acces, on the local listening IP interface, using a web- browser(elinks) and verified that everything is running, the next step will be to configure Nginx to reverse proxy to apache2

5. Nginx, HTTPS reverse-proxying to apache2

In the nginx virtual host configuration file uncomment the proxy_* directives and comment the root and index directives and test by accessing the https://hostname.domain from the outside, the default apache2 static page, in the DocumentRoot should be displayed while apache should give a 200 http response.

It is now time to get on the Apache2.2 SVN and LDAP configuration.

6. Apache2, configuring the LDAP authentication

6.1 Installing the Apache2 needed modules

On the back-end server install the modules for LDAP authentication, as root:

root# a2enmod authnz_ldap

then modify the virtual host configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        <VirtualHost IP_addr:80>

            ServerName hostname.domain

            ErrorLog /path/to/logs/error

            CustomLog /path/to/logs/access combined

            # assign the scm user to this VH

            AssignUserID scm scm-local

            DocumentRoot /scm/home/dir

                        UseCanonicalName on

            AuthType basic

            AuthUserFile /dev/null

            AuthBasicProvider ldap

            AuthName "SCM auth"

            AuthzLDAPAuthoritative on

            AuthLDAPURL "ldap://IP_addr:PORT/ou=people,DC=hostname,DC=domain?uid?sub?"

            require valid-user

            require ldap-group cn=Group_name,ou=group,dc=hostname,dc=domain

        </VirtualHost>

as usual, make a test accessing the hostname.domain trying to authenticate a user with correct credenials and group membership, then with un unprivileged user and be sure to get success and error responses.

7. Apache2, configuring the SVN DAV modules and access

7.1 Installing the dav modules:

as root:

root# a2enmod dav_svn

and modify the virtual host configuration as following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        <VirtualHost IP_addr:80>

            ServerName hostname.domain

            ErrorLog /path/to/logs/error

            CustomLog /path/to/logs/access combined

            # assign the scm user to this VH

            AssignUserID scm scm-local

                        UseCanonicalName on

            <Location /repos>

                DAV svn

                SVNParentPath /path/to/repos

                SVNListParentPath on

                AuthType basic

                AuthUserFile /dev/null

                AuthBasicProvider ldap

                AuthName "SCM auth"

                AuthzLDAPAuthoritative on

                AuthLDAPURL "ldap://IP_Addr:Port/ou=people,DC=hostname,DC=domain?uid?sub?"

                require valid-user

                require ldap-group cn=Scm,ou=group,dc=hostname,dc=domain

            </Location>

        </VirtualHost>

after these changes to the configuration it's possible to use the repositories as either using the svn CLI or web access. The use of UseCanonicalName on is in conjunction with the set destination Nginx configuration, in order to make DAV correctly operating on files and destinations.

8. Subversion, creating and migrating repositories

Since Subversion 1.5 has been released, i took the chance to migrate the repositories to the new version:

on the back-end server, which hosts the SVN repositories, become the 'scm' user and start creating the new repositories:

scm$ svnadmin create repo1

it is a good time now for testing the access to the newly created repository and make some test commit/update just to be sure all the structure is working as wanted;

to migrate the repositories a dump of the old ones is needed, so get on the old svn central repositories machine and issue a dump:

scm$ svnadmin dump repo_name > repo_name_oldversion.dump

and transfer the file containing the dump on the back-end server in the 'scm' home directory, maybe by using a scp copy;

before loading the dump create the repository named as the old one which the dump comes from:

scm$ svnadmin create repo_name

and then load the dump:

scm$ svnadmin load repo_name < repo_name_oldversion.dump

this was a brief example of subversion dump/load cycle.

Conclusions

This was quite a fast tour in configuring such a structure, by following it are not excluded issues, but in this way it should be possible to use a subversion repositories collection by either svn cli or web-access.

Hope it helps.


Posted Nov 22, 2008 in Sysadmin

Moon at -62:37:37.0, 15:37:08.4 observing from Rome, IT


Recent Posts

La Luna by Bert Jansch
Have fun tracking Comet ISON with PyEphem
APOD Full Moon Silhouettes

Sysadmin All Posts

Categories

Astro
Music
all entries feeds   follow me on twitter   my LinkedIn profile  

Powered by Moonwatcher.it ShortPosts.