Version Control with Subversion - httpd, the Apache HTTP server - Per-Directory Access Control
Per-Directory Access Control
It's possible to set up finer-grained permissions using
a second Apache httpd module,
mod_authz_svn
. This module grabs the
various opaque URLs passing from client to server, asks
mod_dav_svn
to decode them, and then
possibly vetoes requests based on access policies defined in
a configuration file.
If you've built Subversion from source code,
mod_authz_svn
is automatically built
and installed alongside
mod_dav_svn
.
Many binary distributions install it automatically as well.
To verify that it's installed correctly, make sure it comes
right after
mod_dav_svn
's
LoadModule directive in
httpd.conf :
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
To activate this module, you need to configure your
Location block to use the
AuthzSVNAccessFile directive, which
specifies a file containing the permissions policy for paths
within your repositories. (In a moment, we'll discuss the
format of that file.)
Apache is flexible, so you have the option to configure
your block in one of three general patterns. To begin,
choose one of these basic configuration patterns. (The
examples below are very simple; look at Apache's own
documentation for much more detail on Apache authentication
and authorization options.)
The simplest block is to allow open access to everyone.
In this scenario, Apache never sends authentication
challenges, so all users are treated as
“anonymous”.
Example 6.1. A sample configuration for anonymous access.
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
</Location>
On the opposite end of the paranoia scale, you can
configure your block to demand authentication from everyone.
All clients must supply credentials to identify themselves.
Your block unconditionally requires authentication via the
Require valid-user directive, and defines
a means to authenticate.
Example 6.2. A sample configuration for authenticated access.
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
# only authenticated users may access the repository
Require valid-user
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
A third very popular pattern is to allow a combination
of authenticated and anonymous access. For example, many
administrators want to allow anonymous users to read certain
repository directories, but want only authenticated users to
read (or write) more sensitive areas. In this setup, all
users start out accessing the repository anonymously. If
your access control policy demands a real username at any
point, Apache will demand authentication from the client.
To do this, you use both the Satisfy Any
and Require valid-user directives
together.
Example 6.3. A sample configuration for mixed
authenticated/anonymous access.
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
# try anonymous access first, resort to real
# authentication if necessary.
Satisfy Any
Require valid-user
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
Once your basic Location block is
configured, you can create an access file and define some
authorization rules in it.
The syntax of the access file is the same familiar one
used by
svnserve.conf
and the runtime
configuration files. Lines that start with a hash
(# ) are ignored. In its simplest form,
each section names a repository and path within it, and the
authenticated usernames are the option names within each
section. The value of each option describes the user's
level of access to the repository path: either
r (read-only) or rw
(read-write). If the user is not mentioned at all, no
access is allowed.
To be more specific: the value of the section-names are
either of the form [repos-name:path] or
the form [path] . If you're using the
SVNParentPath directive, then it's
important to specify the repository names in your sections.
If you omit them, then a section like
[/some/dir] will match the path
/some/dir in
every
repository. If you're using the SVNPath
directive, however, then it's fine to only define paths in
your sections—after all, there's only one
repository.
[calc:/branches/calc/bug-142]
harry = rw
sally = r
In this first example, the user harry has
full read and write access on the
/branches/calc/bug-142 directory in the
calc repository, but the user
sally has read-only access. Any other
users are blocked from accessing this directory.
Of course, permissions are inherited from
parent to child directory. That means that we can specify a
subdirectory with a different access policy for
Sally:
[calc:/branches/calc/bug-142]
harry = rw
sally = r
# give sally write access only to the 'testing' subdir
[calc:/branches/calc/bug-142/testing]
sally = rw
Now Sally can write to the testing
subdirectory of the branch, but can still only read other
parts. Harry, meanwhile, continues to have complete
read-write access to the whole branch.
It's also possible to explicitly deny permission to
someone via inheritance rules, by setting the username
variable to nothing:
[calc:/branches/calc/bug-142]
harry = rw
sally = r
[calc:/branches/calc/bug-142/secret]
harry =
In this example, Harry has read-write access to the
entire bug-142 tree, but has absolutely no
access at all to the secret
subdirectory within it.
The thing to remember is that the most specific path
always matches first. The
mod_authz_svn
module tries to match the path itself, and then the parent
of the path, then the parent of that, and so on. The net
effect is that mentioning a specific path in the accessfile
will always override any permissions inherited from parent
directories.
By default, nobody has any access to the repository at
all. That means that if you're starting with an empty file,
you'll probably want to give at least read permission to all
users at the root of the repository. You can do this by
using the asterisk variable (* ), which
means “all users”:
[/]
* = r
This is a common setup; notice that there's no
repository name mentioned in the section name. This makes
all repositories world readable to all users, whether you're
using SVNPath or
SVNParentPath . Once all users have
read-access to the repositories, you can give explicit
rw permission to certain users on specific
subdirectories within specific repositories.
The asterisk variable (* ) is also
worth special mention here: it's the
only
pattern which matches an anonymous
user. If you've configured your Location
block to allow a mixture of anonymous and authenticated
access, all users start out accessing Apache anonymously.
mod_authz_svn
looks for a
* value defined for the path being
accessed; if it can't find one, then Apache demands real
authentication from the client.
The access file also allows you to define whole groups
of users, much like the Unix /etc/group
file:
[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = harry, sally, joe, frank, sally, jane
Groups can be granted access control just like users.
Distinguish them with an “at” (@ )
prefix:
[calc:/projects/calc]
@calc-developers = rw
[paint:/projects/paint]
@paint-developers = rw
jane = r
Groups can also be defined to contain other
groups:
[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = @calc-developers, @paint-developers
...and that's pretty much all there is to it.
[an error occurred while processing this directive]
|