At this point, you’ve configured authentication, but not authorization. Apache is able to challenge clients and confirm identities, but it has not been told how to allow or restrict access to the clients bearing those identities. This section describes two strategies for controlling access to your repositories.
The simplest form of access control is to authorize certain users for either read-only access to a repository or read/write access to a repository.
You can restrict access on all repository operations by adding
the Require valid-user
directive
to your <Location>
block. Using our previous example, this would mean that only
clients that claimed to be either harry
or sally
and that provided the correct password
for their respective username would be allowed to do anything with the
Subversion repository:
<Location /svn> DAV svn SVNParentPath /var/svn # how to authenticate a user AuthType Basic AuthName "Subversion repository" AuthUserFile /path/to/users/file # only authenticated users may access the repository Require valid-user </Location>
Sometimes you don’t need to run such a tight ship. For example,
Subversion’s own source code repository at http://svn.collab.net/repos/svn allows anyone in the
world to perform read-only repository tasks (such as checking out
working copies and browsing the repository with a web browser), but it
restricts all write operations to authenticated users. To do this type
of selective restriction, you can use the Limit
and LimitExcept
configuration directives. Like the Location
directive, these blocks have
starting and ending tags, and you would nest them inside your <Location>
block.
The parameters present on the Limit
and LimitExcept
directives are HTTP request
types that are affected by that block. For example, if you wanted to
disallow all access to your repository except the currently supported
read-only operations, you would use the LimitExcept
directive, passing the GET
, PROPFIND
, OPTIONS
, and REPORT
request type parameters. Then the
previously mentioned Require
valid-user
directive would be placed inside the <LimitExcept>
block instead of just
inside the <Location>
block:
<Location /svn> DAV svn SVNParentPath /var/svn # how to authenticate a user AuthType Basic AuthName "Subversion repository" AuthUserFile /path/to/users/file # For any operations other than these, require an authenticated user. <LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept> </Location>
These are only a few simple examples. For more in-depth
information about Apache access control and the Require
directive, take a look at the
Security
section of the Apache
documentation’s tutorials collection at http://httpd.apache.org/docs-2.0/misc/tutorials.html.
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 following examples 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.” See Example 6-1.
<Location /repos> DAV svn SVNParentPath /var/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 it defines a means to
authenticate. See Example 6-2.
<Location /repos> DAV svn SVNParentPath /var/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 they want only authenticated users to read (or write to) 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, use both the Satisfy
Any
and Require
valid-user
directives together. See Example 6-3.
<Location /repos> DAV svn SVNParentPath /var/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 you’ve settled on one of these three basic httpd.conf templates, you need to create your file containing access rules for particular paths within the repository. We describe this later in Path-Based Authorization.
The mod_dav_svn module goes
through a lot of work to make sure that data you’ve marked
“unreadable” doesn’t get accidentally leaked. This means
it needs to closely monitor all of the paths and file contents
returned by commands such as svn
checkout and svn update.
If these commands encounter a path that isn’t readable according to
some authorization policy, the path is typically omitted altogether.
In the case of history or rename tracing—for example, running a
command such as svn cat -r OLD foo.c
on a file that
was renamed long ago—the rename tracking will simply halt if one of
the object’s former names is determined to be read-restricted.
All of this path checking can be quite expensive, especially in
the case of svn log. When
retrieving a list of revisions, the server looks at every changed path
in each revision and checks it for readability. If an unreadable path
is discovered, it’s omitted from the list of the revision’s changed
paths (normally seen with the --verbose
option), and the whole log
message is suppressed. Needless to say, this can be time-consuming on
revisions that affect a large number of files. This is the cost of
security: even if you haven’t configured a module such as mod_authz_svn at all, the mod_dav_svn module is still asking Apache
httpd to run authorization checks
on every path. The mod_dav_svn
module has no idea what authorization modules have been installed, so
all it can do is ask Apache to invoke whatever might be
present.
On the other hand, there’s also an escape hatch of sorts, which
allows you to trade security features for speed. If you’re not
enforcing any sort of per-directory authorization (i.e., not using
mod_authz_svn or similar module),
you can disable all of this path checking. In your httpd.conf file, use the SVNPathAuthz
directive as shown in Example 6-4.
<Location /repos> DAV svn SVNParentPath /var/svn SVNPathAuthz off </Location>
The SVNPathAuthz
directive is
“on” by default. When set to “off,” all
path-based authorization
checking is disabled; mod_dav_svn
stops invoking authorization checks on every path it discovers.