This documentation was written to describe the 1.7.x series of Apache™ Subversion®. If you are running a different version of Subversion, you are strongly encouraged to visit http://www.svnbook.com/ and instead consult the version of this documentation appropriate for your version of Subversion.
Both Apache and svnserve are capable of granting (or denying) permissions to users. Typically this is done over the entire repository: a user can read the repository (or not), and she can write to the repository (or not). It's also possible, however, to define finer-grained access rules. One set of users may have permission to write to a certain directory in the repository, but not others; another directory might not even be readable by all but a few special people. As files are paths, too, it's even possible to restrict access on a per file basis.
Both servers use a common file format to describe these
path-based access rules. In the case of Apache, one needs to
load the mod_authz_svn module and then add
the AuthzSVNAccessFile
directive (within
the httpd.conf
file) pointing to your own
access rules file. (For a full explanation, see
the section called “Per-directory access control”.) If
you're using svnserve, you need to make
the authz-db
variable
(within svnserve.conf
) point to your access
rules file.
Once your server knows where to find your access file, it's time to define the rules.
The syntax of the 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, as well as 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 is
either of the form [repos-name:path]
or of the
form [path]
.
Warning | |
---|---|
Prior to version 1.7, Subversion treated repository names and paths in a case-insensitive fashion for the purposes of access control, converting them to lower case internally before comparing them against the contents of your access file. It now does these comparisons case-sensitively. If you upgraded to Subversion 1.7 from an older version, you should review your access files for case correctness. |
If you're using the
SVNParentPath
directive, it's important
to specify the repository names in your sections. If you omit
them, a section such as
[/some/dir]
will match the path
/some/dir
in every
repository. If you're using the SVNPath
directive, however, 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.
Warning | |
---|---|
mod_dav_svn offers a directive,
<Location /svn/calc> SVNPath /var/svn/calc SVNReposName "Calculator Application" … This allows mod_dav_svn to identify the
repository by something other than merely its server directory
basename— |
Of course, permissions are inherited from parent to child directory. That means 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.
Tip | |
---|---|
The thing to remember is that the most specific path always matches first. The server 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 access file 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 no repository
name is mentioned in the section name. This makes all repositories
world-readable to all users. 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 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, 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] jane = r @paint-developers = rw
Another important fact is that group permissions are not
overridden by individual user permissions. Rather, the
combination of all matching permissions is
granted. In the prior example, Jane is a member of the
paint-developers
group, which has read/write
access. Combined with the jane = r
rule,
this still gives Jane read/write access. Permissions for group
members can only be extended beyond the permissions the group
already has. Restricting users who are part of a group to less
than their group's permissions is impossible.
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
Subversion 1.5 brought several useful features to the access file syntax—username aliases, authentication class tokens, and a new rule exclusion mechanism—all of which further simplify the maintenance of the access file. We'll describe first the username aliases feature.
Some authentication systems expect and carry relatively
short usernames of the sorts we've been describing
here—harry
,
sally
, joe
, and so on. But
other authentication systems—such as those which use LDAP
stores or SSL client certificates—may carry much more
complex usernames. For example, Harry's username in an
LDAP-protected system might be CN=Harold
Hacker,OU=Engineers,DC=red-bean,DC=com
. With
usernames like that, the access file can become quite bloated
with long or obscure usernames that are easy to mistype.
Fortunately, username aliases allow you to have to type the
correct complex username only once, in a statement which assigns to
it a more easily digestable alias.
[aliases] harry = CN=Harold Hacker,OU=Engineers,DC=red-bean,DC=com sally = CN=Sally Swatterbug,OU=Engineers,DC=red-bean,DC=com joe = CN=Gerald I. Joseph,OU=Engineers,DC=red-bean,DC=com …
Once you've defined a set of aliases, you can refer to the users elsewhere in the access file via their aliases in all the same places you could have instead used their actual usernames. Simply prepend an ampersand to the alias to distinguish it from a regular username:
[groups] calc-developers = &harry, &sally, &joe paint-developers = &frank, &sally, &jane everyone = @calc-developers, @paint-developers
You might also choose to use aliases if your users' usernames change frequently. Doing so allows you to need to update only the aliases table when these username changes occur, instead of doing global-search-and-replace operations on the whole access file.
Subversion also supports some “magic” tokens
for helping you to make rule assignments based on the user's
authentication class. One such token is
the $authenticated
token. Use this token
where you would otherwise specify a username, alias, or group
name in your authorization rules to declare the permissions
granted to any user who has authenticated with any username at
all. Similarly employed is the $anonymous
token, except that it matches everyone who has
not authenticated with a username.
[calendar:/projects/calendar] $anonymous = r $authenticated = rw
Finally, another handy bit of access file syntax magic is
the use of the tilde (~
) character as an
exclusion marker. In your authorization rules, prefixing a
username, alias, group name, or authentication class token with
a tilde character will cause Subversion to apply the rule to
users who do not match the rule. Though
somewhat unnecessarily obfuscated, the following block is
equivalent to the one in the previous example:
[calendar:/projects/calendar] ~$authenticated = r ~$anonymous = rw
A less obvious example might be as follows:
[groups] calc-developers = &harry, &sally, &joe calc-owners = &hewlett, &packard calc = @calc-developers, @calc-owners # Any calc participant has read-write access... [calc:/projects/calc] @calc = rw # ...but only allow the owners to make and modify release tags. [calc:/projects/calc/tags] ~@calc-owners = r
All of the above examples use directories, because defining access rules on them is the most common case. But is similarly able to restrict access on file paths, too.
[calendar:/projects/calendar/manager.ics] harry = rw sally = r
[61] A common theme in this book!
[62] For more on this, see the blog post Authz and Anon Authn Agony at https://subversion.apache.org/blog/2007-03-27-authz-and-anon-authn-agony.html.