Source

Portfolio / hacktuts / hg / configure_access_control_mercurial.txt

Configuring Access Control with Mercurial
=========================================

Mercurial is a Source Code Management (SCM) tool written in Python which has been gaining popularity over the years. If you are using Mercurial and have been hosting private repositories for yourself and a team that you trust, most of the time the world is pretty good for you! Eventually the time will come when that internal project needs to be made available to a wider audience with read-only permission while still allowing your internal team the ability to commit changes to the repository. Most likely the publicly exposed repository will need to coexist next to private repositories as well. The configuration for this type of setup isn't difficult but does require a little creativity when configuring Apache HTTPD and your Mercurial repositories.

Configuring the Mercurial Repositories
======================================

Configuring the Private Mercurial Repositories
==============================================

The first step to setting up such a configuration is to ensure that the repositories that you want to be private remain that way. To do this we need to explicitly list who is allowed to push and pull from the repository.

file [repo]/.hg/hgrc

<br>
     [web]<br>
     allow_push = harry, john, sally<br>
     allow_read = harry, john, sally<br>

This configuration will only let the authenticated users harry, john and sally push or pull changes to and from the repository. It is important to have this as we don't want to rely solely on Apache for authorization. A common setup with a private team is to allow push and read to anyone and depend on Apache refusing all access to the repository to any unauthenticated user. Since we will be mixing public and private repositories we need to make sure that the private repositories define who is allowed to push and pull from them and not depend solely on Apache for access control.

Configuring the Public Mercurial Repositories
=============================================

The second step is to configure the repositories that you wish to expose to the public. For these files ensure the following lines are in the [repo]/.hg/hgrc file being served up by your web server.

<br>
      [web]<br>
      allow_push = harry, john, sally<br>
      allow_read = *<br>

This will allow authenticated users harry, john and sally to push changes to the repository and allow anyone authenticated or not to pull changes from the repository.

Additional Tips
===============

While talking about securing the repositories, it is also good to ensure that the underlying file permissions are secure as well. The only user that needs access to read and write the files which makeup the repository is the user which Apache HTTPD is running as. This is typically www-data but might be different depending on your operating system and configuration.

<br>
    # chown -R www-data:www-data <hg_repo><br>
    # chmod -R go-rwx <hg_repo><br>

These commands will remove read, write and execute permission from everyone except www-data which in our example is the user running Apache HTTPD.

Configuring Apache HTTPD
========================

Now that the repositories themselves are secured, lets go ahead and adjust our Apache configuration. Apache will be configured to have two entry points into the same repository, one that is publicly available where we rely on the hgwebdir.cgi to expose only those repositories that are publicly readable and another entry point which will force the requester to authenticate. Once the user is authenticated hgwebdir.cgi will show the repositories that are publicly available as well as those that the user has access to.

<br>
    <VirtualHost *:443><br>
        ...<br>
        RewriteEngine On<br>
        RewriteRule ^/private/(.*) /hgwebdir.cgi/$1<br>
        RewriteRule ^/public/(.*) /hgwebdir.cgi/$1<br>
        <Location "/private"><br>
                Require valid-user<br>
                AuthType Basic<br>
                AuthName "Private Mercurial Repositories"<br>
                AuthUserFile [your htpasswd file with valid users/passwords]<br>
        </Location><br>
        ...<br>
    </VirtualHost><br>

Now public users can access the public repositories through https://hgrepos/public/[repo_name] and they will not be presented with a password prompt and will only be able to clone the repositories which are publicly available. The private team can access the same underlying repositories via https://hgrepos/private/[repo_name] and will be prompted for a password once authenticated they should be allowed to clone, pull and push to the repository according to the configuration in the .hg/hgrc file.

Hopefully this post showed a way that you can mix public and private mercurial repositories securely. If you have any other tips or I left something out, please feel free to comment below!

Additional Resources
====================
hgrc Documentation (http://www.selenic.com/mercurial/hgrc.5.html)
HOWTO hgwebdir.cgi (http://mercurial.selenic.com/wiki/HgWebDirStepByStep)
Apache HTTPD Documentation (http://httpd.apache.org/docs/2.2/)