Enterprise-class authentication is a key component of every application used in a corporate environment. Apache Subversion administrators have to comply with the very same constraint as everyone else. In a Microsoft Active Directory environment (or any other KDC implementation), Kerberos authentication is ubiquitous and Apache Subversion shall benefit from it too. This guide will show you how to leverage Kerberos authentication for your Apache Subversion setup and never ever bother with user management and plain text passwords again. Period.
What is Kerberos?
|
Introduction
I have been developing software in a corporate environment with integrated Kerberos authentication
for a couple of years now (mostly Java) along with Apache Subversion as the SCM system of choice.
After gaining profound experience with both and being infected by the ubiquity and magic of Kerberos
authentication, I wanted to the bring best of both worlds together.
Some time later, several months past and numerous improvements to libserf
(Subversion’s HTTP
transport) and mod_spnego
which now has been replaced by mod_auth_gssapi
, it was finally working.
True enterprise-class single sign-on, cryptographically secure, tamper-proof, mutual, free and open
standards authentication. In other words, your corporate users log into their workstations once and
never again (to an application). This documentation addresses a
most wanted feature
"Enterprise Authentication Mechanisms" reported as SVN-3629.
Scope of this Documentation
The scope of this tutorial is to show you how you can expose your Subversion repositories via HTTP
(http://
) securely authenticated through Kerberos
[Actually SPNEGO is performed via HTTP,
by browsers and other clients, and not Kerberos directly. See here
as well as the RFC 4559]
. While the depicted repository
creation supports multiple access methods, it is out of scope how to configure Kerberos authentication
via svn://
and/or svn+ssh://
. For this, you need to take a look at your SASL and/or SSH daemon
configuration. In fact, Subversion’s SASL code is partially inadequate for.
License and Availability
This documentation is licensed under the Creative Commons BY-SA 4.0 license and has been created with the fabulous AsciiDoc tool (version 8.6.10). It is canonically available at https://s.apache.org/svn-enterprise-auth.
Contributing
If you would like to help improve this documentation, please check out the source code and provide patches. Any improvement is welcome, especially proofreading from native English speakers is highly appreciated since I am not a native English speaker.
Acknowledgement
Many thanks go to the Apache Subversion developers making this great tool happen, to the authors of
mod_auth_gssapi
which I stumbled upon on GitHub and finally a special thank you to Lieven Govaerts
who helped me find the last couple of bugs in libserf
related to Kerberos authentication.
Tested Environment(s)
Everything documented here has been tested and is already fully deployed under the following conditions:
Authentication is completely handled by/against a battery of Microsoft Windows Server 2012 R2 (or newer)
domain controllers which are our default KDC implementation. Subversion repositories are served by
FreeBSD 10.4 on Apache Web Server 2.4.29, PHP 5.6.33, Apache Subversion 1.9.7, libserf
1.3.9,
MIT Kerberos 1.15.2 and mod_auth_gssapi
1.6.0 (all from FreeBSD ports).
On the client side following setups are used:
-
Microsoft Windows 7 with Apache Subversion 1.8.x/1.9.x (from CollabNet), TortoiseSVN 1.8.x/1.9.x and Subclipse 1.10.x with JavaHL binding
-
RHEL 6.x with Apache Subversion 1.8.x with MIT Kerberos 1.10.x (from Red Hat and WANdisco repositories)
-
FreeBSD 9.3 and 10.3 with Apache Subversion 1.8.x/1.9.x,
libserf
1.3.9, MIT Kerberos 1.14.4 (all from FreeBSD ports) -
HP-UX 11.31 with Apache Subversion 1.9.x,
libserf
1.3.9, MIT Kerberos 1.13.x (all self-compiled)
This means that you can host your Subversion repositories on any Unix-like operating system and the clients on any operating system.
Requirements
First of all, you should be able to perform administrative tasks through the shell (SSH) with root privileges on your target server.
If you are uncertain about administration or any of the software listed below sounds unfamiliar to you, consult your local Unix admin before you perform any changes with root privileges. |
Do not try with Subversion 1.7! It will not work as it uses libneon as HTTP transport which is
broken for Kerberos authentication with SPNEGO. |
What you will require to complete the setup:
-
Authentication environment:
-
Either Microsoft Active Directory or any Unix-based KDC implementation like MIT Kerberos or Heimdal up and running
-
-
Server environment:
-
A fairly modern Unix-like operating system, FreeBSD or a Linux flavor preferrably, but any will do
-
MIT Kerberos as GSS-API implementation including development resources (header files, etc.).
-
Samba 4 or
msktutil(1)
, if you are in a Microsoft Active Directory environment -
The Apache Web Server 2.4.x including development resources (header files,
apxs
, etc.). -
Apache Subversion 1.8.x or 1.9.x including the Apache module (
mod_dav_svn
) -
mod_auth_gssapi
1.4.1 or newer -
PHP 5.6.x or newer and the Apache module (
mod_php5
)
-
-
Client environment:
-
Any operating system with Kerberos support, e.g., Microsoft Windows or Unix-like with an installed GSS-API implementation.
-
libserf
compiled against that GSS-API implementation -
Apache Subversion 1.8.x/1.9.x
-
A Kerberos principal logged into a domain/realm on Windows or Unix
-
Go on to the next chapter to see how to all components play together.
Looking for Apache Web Server 2.2 support?
Due to the change to |
Installation
Let’s install the necessary components now. I will use generic/symbolic package names which might not exactly match those used by your package management system, you need to figure out real package names.
Compiling from Source
While you can compile everything mentioned above from source, you should rather use the package manager of your operating system unless you know how to properly compile and link those dependencies. If you still want to go that path, have a recent C/C++ compiler like GCC or Clang installed and everything should work. |
Packages
Install the following packages: kerberos
, kerberos-dev
, samba
or msktutil
(if in an Active
Directory environment), apache24
, apache24-dev
, subversion
, apache24-mod-subversion
, php5
,
apache24-mod-php5
, apache24-mod-auth-gssapi
. This might take a while, so be patient. Make sure
that libserf
is also compiled with GSS-API support.
Usage on FreeBSD
FreeBSD users, hooray! All software is straight available from ports. Though, do not use Heimdal from base. It is horribly old and broken. Your clients will crash with a segmentation fault. Make sure that you always either use MIT Kerberos or Heimdal from ports. |
Configuration
The configuration is comprised of several steps. First, we need to configure Kerberos on your
server, then create a Subversion system account, followed by a demo Subversion repository. After
that, we need to expose it through mod_dav_svn
on Apache Web Server via HTTP and enable
mod_auth_gssapi
. Finally, we will configure WebSVN, a web interface for your web browser.
The following will be assumed (adapt to your environment accordingly):
-
Your Kerberos realm is
EXAMPLE.COM
-
Your server hostname is
dev.example.com
-
All Subversion data reside in
/var/svn
which will be referred toSVN_ROOT
-
Apache Web Server
-
Config files reside in
/usr/local/etc/apache24
which will be referred to asAPACHE_CONFDIR
-
Generic web files reside in
/usr/local/www
which will be referred to asWWWDIR
-
Kerberos
Let’s prepare the server for Kerberos first. Basically, you will need a krb5.conf
and a keytab
file. The keytab file will contain the keys for the machine itself and the keys for the HTTP
service (with the appropriate SPN HTTP/dev.example.com
) running on that machine.
Well-managed DNS records are vital, make sure that all KDCs are properly registered with DNS and your server has correct (forward) DNS records. |
If you are in an MIT Kerberos/Heimdal environment, request your admin to create the above for you.
In a Windows environment, configure Samba’s smb.conf
in conformance with your Windows admin.
Create a skeletal krb5.conf
in /etc
:
[libdefaults]
default_realm = EXAMPLE.COM
forwardable = true
dns_lookup_kdc = true
rdns = false
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
Now you can let Samba do the rest with:
# net ads -U <domain admin account> join
# net ads -P keytab create
# net ads -P keytab add HTTP
In both cases, you should have a keytab in /etc/krb5.keytab
.
Execute klist -e -k /etc/krb5.keytab
, the output should resemble this:
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
63 host/dev.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
63 host/dev.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
63 host/dev.example.com@EXAMPLE.COM (arcfour-hmac)
63 host/dev@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
63 host/dev@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
63 host/dev@EXAMPLE.COM (arcfour-hmac)
63 dev$@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
63 dev$@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
63 dev$@EXAMPLE.COM (arcfour-hmac)
63 HTTP/dev.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
63 HTTP/dev.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
63 HTTP/dev.example.com@EXAMPLE.COM (arcfour-hmac)
63 HTTP/dev@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
63 HTTP/dev@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
63 HTTP/dev@EXAMPLE.COM (arcfour-hmac)
Make sure that the system account of the Apache Web Server has read access to the keytab.
Subversion
Now we need to create a system account for Subversion and create a demo repository to get started.
System Account
You can skip this section if you don’t want to have a separate user for Subversion, but want the system account of the web server to own the repositories or if you are on FreeBSD, all is created automatically for you by the Subversion port. |
Following the least privilege principle, all of your Subversion repositories should be owned by a
user who has minimal access to the system. Create, by the means of your OS, a system account svn
(ID < 1000) and a system group svn
(ID < 1000) without a home and default shell. It should look
similar to this in your /etc/passwd
:
svn:*:81:81:Subversion system account:/nonexistent:/usr/sbin/nologin
and in your /etc/groups
:
svn:*:81:
Demo Repository
The final step is to create a demo repository enterprise
in $SVN_ROOT/repos
as root
:
# cd $SVN_ROOT/repos
# umask 0027
# svnadmin create "enterprise"
# chown -R svn:svn "enterprise"
# cd "enterprise"
# rm README.txt conf/{passwd,authz,svnserve.conf}
# rm -rf locks/
# chmod ug+x conf/hooks-env.tmpl
# find db -type d -perm 0750 -exec chmod g+s '{}' \;
# find . -type d -perm 2750 -exec chmod g+w '{}' \;
# chmod g+w db/{current,write-lock,txn-current,txn-current-lock}
# chmod g+ws .
Set a sane umask during creation | |
Create the repository and change the owner | |
Remove unnecessary files. Retain svnserve.conf if you intend to access the repository via
svn:// too. The authz is not necessary here because we will use a global one for all
repositories. You may move it somewhere else. locks/ is created for legacy reasons and can be
safely removed.
| |
Permissions are a common pitfall, set appropriate ones to avoid errors during access. The commands may vary on your operating system, see below. |
Verify your repository with tree -pug
after creation, ownership and permissions must look like
this:
.
|-- [drwxr-x--- svn svn ] conf
| `-- [-rwxr-x--- svn svn ] hooks-env.tmpl
|-- [drwxrws--- svn svn ] db
| |-- [-rw-rw---- svn svn ] current
| |-- [-r--r----- svn svn ] format
| |-- [-rw-r----- svn svn ] fs-type
| |-- [-rw-r----- svn svn ] fsfs.conf
| |-- [-rw-r----- svn svn ] min-unpacked-rev
| |-- [drwxrws--- svn svn ] revprops
| | `-- [drwxrws--- svn svn ] 0
| | `-- [-r--r----- svn svn ] 0
| |-- [drwxrws--- svn svn ] revs
| | `-- [drwxrws--- svn svn ] 0
| | `-- [-r--r----- svn svn ] 0
| |-- [drwxrws--- svn svn ] transactions
| |-- [-rw-rw---- svn svn ] txn-current
| |-- [-rw-rw---- svn svn ] txn-current-lock
| |-- [drwxrws--- svn svn ] txn-protorevs
| |-- [-rw-r----- svn svn ] uuid
| `-- [-rw-rw---- svn svn ] write-lock
|-- [-r--r----- svn svn ] format
`-- [drwxr-x--- svn svn ] hooks
|-- [-rwxr-x--- svn svn ] post-commit.tmpl
|-- [-rwxr-x--- svn svn ] post-lock.tmpl
|-- [-rwxr-x--- svn svn ] post-revprop-change.tmpl
|-- [-rwxr-x--- svn svn ] post-unlock.tmpl
|-- [-rwxr-x--- svn svn ] pre-commit.tmpl
|-- [-rwxr-x--- svn svn ] pre-lock.tmpl
|-- [-rwxr-x--- svn svn ] pre-revprop-change.tmpl
|-- [-rwxr-x--- svn svn ] pre-unlock.tmpl
`-- [-rwxr-x--- svn svn ] start-commit.tmpl
9 directories, 22 files
If all fits, your repository is now ready to use.
Apache Web Server
A few remaining steps are now necessary to expose your repositories via HTTP. Expose them and have them properly secured.
Since the |
It is completely up to you where you put the following config whether in httpd.conf
, an included
svn.conf
or else. What matters is that the config is sane and accepted by the server. I will
refer to it as $APACHE_CONFDIR/svn.conf
.
Repositories (mod_dav_svn
)
Open up $APACHE_CONFDIR/svn.conf
and activate the Apache module:
<Location "/repos/svn">
DAV svn
SVNParentPath /var/svn/repos
SVNListParentPath On
</Location>
Instruct the web server to reload the configuration. This will happily serve all repositories from
$SVN_ROOT/repos
automatically.
Check now whether you can obtain a working copy of the newly created repository:
$ svn co http://dev.example.com/repos/svn/enterprise
Subversion will tell you, Checked out revision 0
, as usual.
Authentication (mod_auth_gssapi
)
The repository is still unprotected, let’s have all users authenticate to the web server. Open up
your svn.conf
again and add the following before the previous snippet:
<LocationMatch "/repos/(web)?svn">
AuthType GSSAPI
AuthName "Enterprise Subversion Repositories"
GssapiConnectionBound On
GssapiSignalPersistentAuth On
Require valid-user
</LocationMatch>
Update your working copy with svn up
and check your web server access log file. If something went
wrong Subversion will say:
Updating '.':
svn: E120190: Unable to connect to a repository at URL 'http://dev.example.com/repos/svn/enterprise'
svn: E120190: Error running context: An error occurred during authentication
and the logs:
<IP address> - - [18/Mar/2016:21:17:30 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 401 553
<IP address> - - [18/Mar/2016:21:18:02 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 401 553
Verify that you are logged in with a domain account or have a ticket cache filled by kinit
.
Rerun the update and the logs should say:
<IP address> - - [18/Mar/2016:20:58:37 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 401 553
<IP address> - michael-o@EXAMPLE.COM [18/Mar/2016:20:58:37 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 200 200
<IP address> - michael-o@EXAMPLE.COM [18/Mar/2016:20:58:37 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 200 97
<IP address> - michael-o@EXAMPLE.COM [18/Mar/2016:20:58:37 +0100] "OPTIONS /repos/svn/enterprise HTTP/1.1" 200 200
<IP address> - - [18/Mar/2016:20:58:42 +0100] "REPORT /repos/svn/enterprise/!svn/me HTTP/1.1" 401 553
<IP address> - michael-o@EXAMPLE.COM [18/Mar/2016:20:58:42 +0100] "REPORT /repos/svn/enterprise/!svn/me HTTP/1.1" 200 641
All is well, your request was authenticated. As a last test, perform a commit and have a look at the log:
r1 | michael-o@EXAMPLE.COM | 2016-03-18 21:14:04 +0100 (Fri, 18 Mar 2016) | 1 line
Your message goes here...
Authentication is complete, as you can see there are Kerberos principals stored in your repository’s metadata.
Authorization (authz
)
You are probably not going to be satisfied with authentication only, are you? Limiting read and
write access is crucial. Fortunately, Subversion has a simple but yet effective approach with the
authz
file. Copy the aforementioned authz
from the demo repository to $SVN_ROOT/auth/authz
.
This file includes some documentation about the format employed and some examples. Feel free to
remove those examples because we will add our own authorization configuration for all repositories
in one single file. After you have copied it, open up your svn.conf
again and add the following
line to your DAV location directive:
AuthzSVNAccessFile /var/svn/auth/authz
Don’t forget to reload Apache Web Server’s config again.
We are ready to take on authz
now. Open it and add/modify the following:
[groups]
enterprise-rw = michael-o@EXAMPLE.COM
enterprise-ro = john.doe@EXAMPLE.COM
[enterprise:/]
@enterprise-rw = rw
@enterprise-ro = r
Update your working copy, there should be no change. Now ask your colleague John Doe and someone else to check out and commit some change. While John Doe will be able to check out, someone else will fail, but John’s commit will fail too:
svn: E175013: Unable to connect to a repository at URL 'http://dev.example.com/repos/svn/enterprise'
svn: E175013: Access to '/repos/svn/enterprise' forbidden
If you are uncertain whether your authorization configuration is correct, use |
WebSVN
WebSVN offers your a nice browser-friendly view of your repositories and much more. It is added to the web server and configured for your repositories. I am personally not very fond of ViewVC’s GUI.
Download version 2.4.0
of my public fork of WebSVN and extract it to $WWWDIR/websvn
. Make sure that the directory
and everything beneath can be read by the web server or is the owner of it.
You can, of course, install WebSVN 2.3.3 from your package management system, but it won’t include all changes from trunk as well as some patches I have applied to. In this case, you have to create a diff between 2.3.3 and my trunk and apply it to your distribution. |
We need now to create a minimal config.php
in $WWWDIR/websvn/include
and add these
configuration options:
<?php
$config->setSVNCommandPath('/usr/local/bin');
$config->setGeshiScriptPath('/usr/local/lib/php/geshi');
$config->parentPath('/var/svn/repos', null, false, true, 'http://dev.example.com/repos/svn');
$config->addTemplatePath($locwebsvnreal.'/templates/calm/');
$config->useMultiViews();
$config->useAccessFile('/var/svn/auth/authz');
$config->useGeshi();
Assumes that all Subversion binaries reside in /usr/local/bin . Change to your OS configration
accordingly.
| |
Assumes that GeSHi resides in /usr/local/lib/php/geshi . Change to your OS configration
accordingly.
|
You may also inspect |
Then, open up the very same $APACHE_CONFDIR/svn.conf
and add the following:
Alias /repos/websvn "/usr/local/www/websvn"
<Directory "/usr/local/www/websvn">
Require all granted
Options MultiViews
MultiviewsMatch Any # Maybe optional
DirectoryIndex browse.php
</Directory>
Instruct the web server to reload the configuration. This will happily serve all repositories from
$SVN_ROOT/repos
automatically for your web browser too. Check this by navigating to
http://dev.example.com/repos/websvn
. You should see the repositories you have access to.
All configuration is now completed and set up correctly.
Further Outlook
So what’s next? Kerberos does authentication only, but I like centralized authorization too.
Microsoft has extended Kerberos by embedding authorization information into the service ticket in
the PAC data structure. In other words,
one can expose Windows groups (more specifically their SIDs)
to require-group
by parsing this structure. Unfortunately, Subversion cannot make use of them, due
to SVN-2338 and SVN-4603.