Adventures in Freelancing
Setting Up Client Mercurial Repositories
Hosting multiple mercurial repositories isn’t too tricky, there are various tutorials scattered around the web that will get you up and running. However, the security setups in these tutorials are somewhat lacking. This is particularly true if you need fine grained control over not only who gets to PUSH, but also who gets to PULL from the repositories.
Our goal here is to host as many repositories as we’d like, but only allow client access on a per-repository basis. If I set up repository A for client A, I don’t want client A to be able to pull from repository B.
Let’s start by describing our starting point. . All of the tutorials I’ve found get you set up with something like this. We’ve installed mercurial somewhere, and copied the hgwebdir.cgi file to our webroot, and configured it with a hgweb.config file.
Also, there is an .htaccess file at the web root that both limits POST and PUT access to users specified in a password file .htpasswd, which is made with the htpasswd command.
# .htaccess file at webroot
Options +ExecCGI
RewriteEngine On
# / for root directory; specify a complete path from / for others
RewriteBase /
RewriteRule ^$ hgwebdir.cgi [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) hgwebdir.cgi/$1 [QSA,L]
AuthType Basic
AuthName My Hg Repositories
AuthUserFile /path/to/webroot/.htpasswd
<Limit POST PUT>
Require valid-user
</Limit>
The first portion routes all requests through the hgwebdir.cgi script, unless the request is for an existing file.
What we’re interested in is the second part. The tutorials go into the details, but in summary what is happening is that any POST or PUT requests will be authenticated using Basic authentication against the password file .htpasswd. This covers access to ALL the repositories.
There are a couple of problems here. First, with the .htaccess file above, our security related files are openly accessible to everyone. We can add a FilesMatch directive to hide our security files:
<FilesMatch "\.(htaccess|htpasswd|config|bak|ini)$"> Order allow,deny Deny from all </FilesMatch>
The second problem is that everyone can still see all of the repositories. Since these are client repos, I don’t want the random browser to stumble across them. That’s fixed easily enough, just change
<Limit POST PUT>
to
<Limit POST PUT GET>
Now ALL requests are met with a request for authentication. It’s not the prettiest thing in the world, but it works for now. Only clients in the .htpasswd file can view the web portal.
Now to configure access to the repositories themselves. Our security settings will go in each repository’s hgrcfile. The two settings we are interested are allow_push and allow_read. Each take a comma-separated list of authorized users. These go in the [web] section of the configuration file.
[web] allow_read = me,client1,client2 allow_push = me,client1
It’s worth noting that the default for allow_read is to allow all, but the default for allow_push is to deny all.
The major remaining limitation is that once I add a client to the .htpasswd file, they have access to the whole web interface, which lets them view other repositories. The solution is to add hidden = true to the hgrc. This hides the repository from the web directory listing at the root, which lists all of the available repos, but will still serve the repos' web page if accessed directly.
So with a repository 'test' set with hidden = true, it won't show up at http://myreposerver/, but it will still be visible at http://myreposerver/test.
To make it easy to add new repositories, I've created an 'empty' repository that already has an hgrc file configured pretty much the way I want. For reference, here's what I'm using:
[web] contact = Chris Lawlor description = Empty Mercurial Repository. Copy this to create client repos. # Repository name to use in the web interface. Default is current working directory #name = ## ACCESS CONTROL ## allow_push = clawlor allow_read = clawlor, fakeclient, fakeclient3 # hide repo from the directory hidden = true
There are a lot of other settings that can go into the hgrc file that control various aspects of the repository's presentation. Also, most or all of those settings can be made global by putting them in the hgweb.config file located at the webroot.
Now when I want a new repository, I can simple copy the 'empty' repository, change a few bits in the hgrc file, and add new users to the .htpasswd file.
| Print article | This entry was posted by clawlor on May 24, 2010 at 3:31 pm, and is filed under Dev Tools. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |