Skip to content

Path-Based Authorization in SVN

What exactly *is* path-based authorization, anyway? In short, its a way to restrict who can see or change the content in SVN based on the location of the content inside the SVN repository. It uses a set of rules (stored in a text file), and those rules are applied every time a read or write operation is made against the repository.

I'll illustrate by way of an example. Here is what my repository looks like on disk:

/svn
    /repos               <--REPOSITORY #1
    /repos2
        /ecit            <--REPOSITORY #2
        /repos_ast       <--REPOSITORY #3
    /repos3              <--REPOSITORY #4

Each of the repositories contains all the directories used by SVN[^1]. But the /repos2 folder isn't a repository itself. Instead, it contains 2 separate repositories: /ecit and /repos_ast. Those were copied to this machine by a previous administrator and I don't want to modify them.

Unfortunately, I cant expose the root directory (/svn) because it isn't a repository. Instead, I need to expose each of the main repositories: /repos, /ecit, /repos_ast, and /repos3. Luckily, there is some magic I can do with the /repos2 folder to simplify things.

The setup for this arrangement has two parts

  • telling Apache what URI to associate with each repository, and preparing it to use SVN, and
  • setting up the proper SVN authorizations so that people have access to the repositories and projects they need

Apache Configuration

The Apache configuration is really what holds the system together. It brings the authentications system (i.e. the Windows domain) together with its own authorization system (a config file) to determine who gets access to what. It sounds complicated, but its not. I'll explain each repository's configuration separately.

Repository #1

The first repository (/repos) is fairly straightforward. Here is an excerpt from the Apache httpd.conf file. The SVNPath line declares the disk location of the repository, and the AuthzSVNAccessFile line declares where the authorization rules are stored.

<Location /svn/repos>
  DAV svn
  SVNPath C:\svn\repos
  AuthName "SVN Server"
  AuthType SSPI
  SSPIAuth On
  SSPIAuthoritative On
  SSPIDomain NA
  SSPIOfferBasic On
  SSPIBasicPreferred On
  Require valid-user 
  AuthzSVNAccessFile C:\svn\svnaccess.conf
</Location>

Here is the relevant section from my svnaccess.conf file:

[groups]
team1 = na\cfreyer, na\rsmith, .....
team2 = na\joe, na\bill, ...
admins = na\cfreyer, ...

[/]
@admins = rw
@team1 = r
@team2 = r

[/Project1]
@team1 = rw
@team2 = r

[/Project2]
@team2 = rw

[/SecretProject]
na\cfreyer = rw

You can see that the people are grouped by team into. admins group has read-write access to the entire repository (for creating new project directories), but other uses have read-only access. In Project1, team1 can write to the project but team2 can only read. In Project2, only team2 can see it, and they can also write. And in SecretProject, only one person can read or write to it. This is a very flexible arrangement.

Repository #2

Repository #2 (the directory on disk) contains 2 SVN repositories: ecit and repos_ast. I decided to manage these two together (meaning they share a single authorization file). The Apache setup is almost the same as for repository one. Notice that I specified a different location for the AuthzSVNAccessFile though.

<Location /svn/repos2>
    DAV svn
    SVNParentPath C:\svn\repos2
    AuthName "SVN Repos 2"
    AuthType SSPI
    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain NA
    SSPIOfferBasic on 
    SSPIBasicPreferred On
    Require valid-user 
    AuthzSVNAccessFile C:\svn\repos2\svnaccess.conf
</Location>

That forces users to access the repository with a /repos2 prefix, so they know they are in a different repository just by looking at the SVN URL. Here is a section of the AuthzSVNAccessFile:

[groups]
...similar definitions as above...

[ecit:/MyProject]
@myteam = rw

[repos_ast:/OtherProject]
@otherteam = rw

You can see that each location is prefixed with the name of the repository and a colon (i.e. ecit: or repos_ast:). The user won't type the repository name when they access the SVN repository. Instead, the URL will be something likehttp://hostname/repos2/MyProject. This is simple and easy to follow for the user, and it hides the fact that the projects are actually stored in different repositories.

Technically, I could have done all my repositories with this kind of setup. The only drawback is that I have to ensure that projects in the different repositories aren't named the same. I can't have "ecit:/MyProject" and a repos_ast:/MyProject. One of them would be hidden. If this situation is likely for you, then don't combine your repositories like I did.

Repository #3

<Location /svn/repos3>
    DAV svn
    SVNPath C:\svn\repos3
    AuthName "SVN Repos 3"
    AuthType SSPI
    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain NA
    SSPIOfferBasic On
    SSPIBasicPreferred On
    Require valid-user 
    AuthzSVNAccessFile C:\svn\svnaccess.conf
</Location>

[^1] it contains the /conf, /dav, /db, /hooks, and /locks folders