Setting up a Secure Subversion Server
by
Dru Lavigne, author of
BSD Hacks
Recently a client hired a team of web developers to assist his overworked web administrator. They asked me to set up a revision-control system to ensure that no one on the team inadvertently overwrote another member's work and to give the administrator the flexibility of rolling back to any version of a file.
My first thought was Subversion, as it is the revisioning system used with my editor when
writing BSD Hacks A search for
subversion in the
Ports Collection indicated that there are also several related ports. For example,
esvn looked like an excellent match for the client, as this GUI front end works from Unix, Mac OS X, and Windows. That's perfect for a web development team short on Unix skills who would be accessing data stored on a FreeBSD server from non-FreeBSD operating systems.
This week's article demonstrates how to create a secure repository using Subversion. The next installment will show how to train your users to access the repository using a GUI client.
Preparing the System
In my scenario, it was important that only the members of the development team have access to the repository. We also chose to have the repository on a system separate from the actual web server and left it up to the web administrator to copy over files from the repository to the web server as he saw fit.
To accomplish this, start by creating a backup of the existing directory structure you wish to put under revision control, and send it securely to the repository server. In my case, I backed up the www
data on the web server to an internal server at 192.168.2.2.
# tar czvf - /usr/local/etc/www/data | ssh dru@192.168.2.2 "cat > www.tar.gz"
Next, on the repository system, create a new group called svn
and add to it any existing user accounts that need access to the repository. For example, I added my existing web administrator as I created the group by adding this line to /etc/group:
# vi /etc/group
svn:*:3690:webadmin
Then, create a new user called svn
and, if necessary, any missing user accounts that need access to the repository. Make sure each account is a member of the svn
group and has a password and a valid shell. I used sysinstall
to create user accounts for the new web developers. When I finished, I double-checked the membership of the svn
group. It looked something like this:
# grep svn /etc/group
svn:*:3690:webadmin,devel1,devel2
Dealing with umask
Before installing Subversion, take a close look at the existing umask
for the svn
user. On my FreeBSD system it was:
# su -l svn
% umask
022
In Unix, the umask
value determines the default permissions of a newly created directory or file. It does this by defining which permissions to disable. If you remember:
r = 4
w = 2
x = 1
you'll see that this umask
doesn't turn off any (0) permissions for the user (svn
); it turns off write (2) for the group (svn
); and it turns off write (2) for world.
Because the members of the svn
group should be able to write to the repository, change that group 2
to a 0
. If you don't want nongroup members even to be aware of the existence of the repository, also change the world 2
to a 7
.
The easy part is changing the umask
for the svn
user's shell. If it uses csh
:
% vi ~svn/.cshrc
then find the existing umask
line and change it to either 002
or 007
.
If your svn
user has a shell other than csh
, make your edit in your chosen shell's configuration file.
Once you've saved your changes to ~svn/.cshrc (or wherever), don't forget to tell the shell:
% source ~svn/.cshrc
Repeat the umask
command to verify that your changes have taken place.
Installing Subversion with the correct umask
If you chose a umask
of 002
, you can compile a wrapper into Subversion when you build it from the ports collection. If you chose a umask
of 007
or prefer to install the precompiled version of Subversion, create a wrapper script to ensure that the Subversion binaries use your umask
value.
To compile in a wrapper that sets a umask
of 002
:
# cd /usr/ports/devel/subversion
# make -DWITH_SVNSERVE_WRAPPER install clean
Alternatively, to install the precompiled binary:
# pkg_add -r subversion
Note: before installing by either method, finish reading the article. You may find some additional compile options that interest you.
If you didn't compile in your wrapper, move your existing binary and create your own wrapper script:
# mv /usr/local/bin/svn /usr/local/bin/svn.orig
# vi /usr/local/bin/svn
#!/bin/sh
#wrapper script to set umask to 007 on subversion binaries
umask 007
/usr/local/bin/svn.orig "$@"
Set your umask
to either 002
or 007
so that it is the same as the umask
for your svn
user.
Don't forget to make your wrapper script executable:
# chmod +x /usr/local/bin/svn
Creating the Repository
Now that your environment is set up properly, you're ready to create the repository itself. Log in as the user svn
to ensure that both the svn
user and the svn
group own the files you create in the repository. From /usr/home/svn/, type:
% svnadmin create repository
In this example, I've called my repository repository
. You can choose any name that is useful to you.
svnadmin create
simply creates the directory infrastructure required by the Subversion tools:
% ls -F repository
README.txt dav/ format locks/
conf/ db/ hooks/
Notice that db
directory? By default, Subversion uses databases to track changes to the files that you place under revision control. This means that you must import your data into those databases.
At that point, I untarred my backup so that I had some data to import. If you do this, don't restore directly into the ~svn/repository directory. (It's a database, remember?) Instead, I first made a new directory structure:
% pwd
/usr/home/svn
% mkdir www && cd www
% mkdir branches tags trunk
% cd trunk
% tar xzvf /full/path/to/www.tar.gz .
% cd
That made the svn
user's home directory look like:
% ls -F ~svn
repository/ www/
Importing the Data
Next, it's time to import the information from ~svn/www/
into the Subversion databases. To do so, use the svn import
command:
% svn import www file:///usr/home/svn/repository/www -m "initial import"
svn import
is one of many svn
commands available to users. Type svn help
to see the names of all the available commands. If you insert one of those commands between svn
and help
, as in svn import help
, you'll receive help on the syntax for that specified command.
After svn import
, specify the name of the directory containing the data to import (www
). Your data doesn't have to be in the same directory; simply specify the full path to the data, but ensure that your svn
user has permission to access the data you wish to import. Note: once you've successfully imported your data, you don't have to keep an original copy on disk. In my case, I issued the command rm -Rf www
.
Next, notice the syntax I used when specifying the full path to the repository. Subversion supports multiple URL schemas or "repository access" RA modules. Verify which schemas your svn
supports with:
% svn --version
svn, version 1.1.3 (r12730)
compiled Mar 20 2005, 11:04:16
Copyright (C) 2000-2004 CollabNet.
Subversion is open source software, see http://subversion.tigris.org/
This product includes software developed by CollabNet (http://www.Collab.Net/).
The following repository access (RA) modules are available:
* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
- handles 'http' schema
- handles 'https' schema
* ra_local : Module for accessing a repository on local disk.
- handles 'file' schema
* ra_svn : Module for accessing a repository using the svn network protocol.
- handles svn schema
Because I wished to access the repository on the local disk, I used the file:///
schema. I also appended www
at the very end of the URL, as I wish that particular part of the repository to be available by that name. Yes, you can import multiple directory structures into the same Subversion repository, so give each one a name that is easy for you and your users to remember.
Finally, I used the -m
message switch to append the comment "initial import"
to the repository log. If I hadn't included this switch, svn
would have opened the log for me in the user's default editor (vi
) and asked me to add a comment before continuing.
This is a very important point. The whole reason to install a revision control system is to allow multiple users to modify files, possibly even simultaneously. It's up to each user to log clearly which changes they made to which files. It's your job to make your users aware of the importance of adding useful comments whenever an svn
command prompts them to do so.
Deciding Upon a URL Schema
Congratulations! You now have a working repository. Now's the best time to take a closer look at the various URL schemas and choose the access method that best suits your needs.
Chapter 6 of the freely available e-book Version Control with Subversion gives details about the possible configurations. You can choose to install the book when you compile the FreeBSD port by adding -DWITH_BOOK
to your make
command.
If all of your users log in to the system either locally or through ssh
, use the file:///
schema. Because users are "local" to the repository, this scenario doesn't open a TCP/IP port to listen for Subversion connections. However, it does require an active shell account for each user and assumes that your users are comfortable logging in to a Unix server. As with any shell account, your security depends upon your users choosing good passwords and you setting up repository permissions and group memberships correctly. Having users ssh
to the system does ensure that they have encrypted sessions.
Another possibility is to integrate Subversion into an existing Apache server. By default, the FreeBSD port of Subversion compiles in SSL support, meaning your users can have the ability to access your repository securely from their browsers using the https://
schema. However, if you're running Apache 2.x instead of Apache 1.x, remember to pass the -DWITH_MOD_DAV_SVN
option to make
when you compile your FreeBSD port.
If you're considering giving browser access to your users, read carefully through the Apache httpd configuration section of the Subversion book first. You'll have to go through a fair bit of configuration; fortunately, the documentation is complete.
A third approach is to use svnserve
to listen for network connections. The book suggests running this process either through inetd
or as a stand-alone daemon. Both of these approaches allow either anonymous access or access once the system has authorized a user using CRAM-MD5. Clients connect to svnserve
using the svn://
schema.
Anonymous access wasn't appropriate in my scenario, so I followed the configuration options for CRAM-MD5. However, I quickly discovered that CRAM-MD5 wasn't on my FreeBSD system. When a Google search failed to find a technique for integrating CRAM-MD5 with my Subversion binary, I decided to try the last option.
This was to invoke svnserve
in tunnel mode, which allows user authentication through the normal SSH mechanism as well as any restrictions you have placed in your /etc/ssh/sshd_config file. For example, I could use the AllowUsers
keyword to control which users can authenticate to the system. Note that this schema uses svn+ssh://
.
The appeal of this method is that I could use an existing authentication scheme without forcing the user to actually be "on" the repository system. However, this network connection is unencrypted; the use of SSH is only to authenticate. If your data is sensitive, either have your users use file://
after ssh
ing in or use https://
after you've properly configured Apache.
If you decide to use the svnserve
server and you compiled in the wrapper, it created a binary called svnserve.bin. Users won't be able to access the repository until:
# cp /usr/local/bin/svnserve.bin /usr/local/bin/svnserve
That's it for this installment. In the next column, I'll show how to start accessing the repository as a client.
Dru Lavigne is an instructor at Marketbridge Technologies in Ottawa and the maintainer of the Open Protocol Resource.
posted on 2005-08-19 22:03
R.Zeus 阅读(472)
评论(1) 编辑 收藏 所属分类:
SERVER