May 13, 2010

Setting up and configuring Mercurial in a Windows/IIS/Active Directory environment - Part 3/4

Part 3: Locking down security using Active Directory

This blog post is part of a four part series for getting Mercurial up and running in a Windows environment and hosting it on IIS 5.1 (i.e. Windows Server 2003).

  1. Part 1 Getting Mercurial set up in IIS and hosting a repository at http://hg.mydomain.com/
  2. Part 2 Getting IIS to hide hgwebdir.cgi in the URL for your Mercurial repositories.
  3. Part 3 Locking down security using Active Directory so that only authorized users can view, clone, pull and/or push to a repository.
  4. Part 4 Customizing the theme/skin of the web interface of your Mercurial repositories.

Demonstration environment setup:

For a while now I've had Mercurial set up and running nicely on IIS, and I've got ISAPI Rewriter running so that my URLs don't include the ugly hgwebdir.cgi in every URL. The current project of the day is authentication and repo security but if you're not set up yet and still need to get going, refer back to the previous posts...

I found a bunch of articles on how to do this in Apache using configuration modules but hadn't found anything about using a AD/IIS setup.

My first step is to decide on my repository structure which needs to be flexible enough that I can have multiple 'clients' (or teams if this is hosted on the company LAN). I figure the following convention should be flexible enough - at least for this blog post.

<Root>\Repositories\<Client>[\<Team>]\<Project>

  • D:\Mercurial\HgWeb - this contains my HgWeb setup which is detailed here
  • D:\Repositories\Client1\Project1
  • D:\Repositories\Client2\Project1
  • D:\Repositories\Client2\Project2
  • D:\Repositories\Client3\Project1
  • D:\Repositories\Client3\Project2
  • D:\Repositories\Client3\Project3

On a corporate LAN you could equally replace Clientn with a team name or just that part of the structure altogether and just have your project folders directly under the repository folder... whatever your structure is doesn't matter, it just needs to work for your organizational patterns.

Before you start with the following security steps, you should be aware that this is written from a least secure to most ideal sequence. This blog post is to help you understand the security mechanisms to use and you shouldn't follow this sequence in an environment that requires high security! You have been warned.

Lockdown - Step 0 [Allow everyone to clone/pull/push]

Let's start out simple - open the hgweb.config file in D:\Mercurial\HgWeb directory and add the configuration to allow all users to push to the repository. This goes in the [web] section of the configuration like so:

[web]
allow_push = *

So [using conventions determined by my previous blog posts], everyone can look at or clone a repository by going to http://hg.mydomain.com/Clientn/Projectn where n can be replaced with a corresponding client or project. Also, everyone can push to the repository - security is wide open. That's not really what we want. But it's a starting point.

Lockdown - Step 1 [Allow only domain users to clone/pull/push]

I don't want the general public having access to my repositories, I want to only give access to authorized parties. Client1 should only be able to access their own projects, likewise with clients 2 and 3.

To do this, we need to edit the authentication in IIS so that only domain users can view resources in this website.

  1. Open Internet Information Services Manager from Administrative Tools.
  2. Right click the website and select properties.
  3. Click the directory security tab.
  4. In the Authentication and access control section, click the Edit button.
  5. Uncheck Enable anonymous access option.
  6. Check the Basic authentication (password is sent in clear text) option.
  7. Enter your default domain - this will be included with any username as it is used for authentication i.e. if your credentials are MYDOMAIN\User1 then your default domain should be MYDOMAIN so that your user doesn't need to enter MYDOMAIN\user1 as his credentials, but can just enter user1.
  8. Enter the realm in the case of my repositories would be hg.mydomain.com - this is the fully qualified domain name for your repository on the web.

CAVEAT: Mercurial requires basic authentication to be used, which means that unless you want your password transmitted in clear text over the internet - you'd best be using SSL.

You can obtain an SSL certificate from a number of well documented places, so I won't go into that any further here. Just to say that you need to make the following security choice:

  • Require Windows Authentication - Mercurial won't be able to authenticate.
  • Use Basic Authentication and no SSL certificate - Mercurial will be able to authenticate, but your credentials are transmitted in a readily readable format over the open internet for anyone with the know-how to extract and exploit.
  • Use Basic Authentication and an SSL certificate - Mercurial will be able to authenticate over SSL so your credentials, and indeed all communication between the client and server will be encrypted.
  • Install SSH and access your repositories via this method instead of through IIS. But I want everything in one place, so IIS wins from a simplicity standpoint.

So now only users who have an account in Active Directory can access the repositories, but nobody else can. Great...but that's not enough.

Lockdown - Step 2 [Allow only specific domain security groups access to a repository]

I don't want everyone with an active directory account being able to access all (or in some cases any) repositories. For instance, I don't want User2 accessing my projects, I only want people from my team accessing my projects.

Create a security group to manage the domain users that can access a repository:

  1. Open Active Directory Users and Computers from Administrative Tools
  2. Create a security group for Client1 - for the purpose of this blog post, I'll call it Client1Group
  3. Add users that have read or write privileges for Client1's projects

Once we are done with this stage of lockdown, members of this security group will be able to read and write to all of Client1's repositories but nobody else will be able to access it.

Assign access privileges to the security group:

  1. Open Windows explorer and navigate to the repository you want to lock down. I will lock down my Client1 folder which contains all of Client1's repositories.
  2. Open the folder properties by right clicking the folder and clicking properties.
  3. Click the security tab.
  4. Click Advanced button and uncheck Allow inheritable permissions from the parent to propogate to this object and all child objects. Include these with entries explicitly defined here. option.
  5. Click OK.
  6. Select Copy to copy the inherited permissions up from the parent directory for now - this way we're starting with the folder as it was in its initial state.
  7. Click OK again.
  8. You will now be back to the original properties window.
  9. Remove the Users group.
  10. Add our Client1Group security group and assign them Read & Execute permissions [List Folder Contents and Read permissions will be implied by these also].
  11. Click OK.

Now those users you assigned to the Client1Group security group will have access to be able to view Client1's repository and indeed, it won't even be displayed to another user if they log in.

Lockdown - Step 3 [Allow only specific group members to push to a repository]

This is done in the hgrc file found in the .hg/hgrc folder of each repository. If one doesn't exist, create it the file doesn't have an extension, it's a plaintext file called just hgrc. If a file exists, you can edit it with notepad or whatever text editor you use. Find the [web] section in the file, if one doesn't exist, add it and add/modify the push rule:

[web]
allow_push = <user1>[,<user2>]...[,<usern>]

Specify each of the usernames of the group that should be able to push to the repository in comma delimited form.

Now everyone contained in the Client1Group security group will be able to view and clone the repository, but only those users you specified will be able to push back up to it. Nobody else will be able to see or access the repository either through the file system or via http://hg.mydomain.com/

Job done!

Next - customizing the look and feel of the Mercurial web interface...

7 comments:

  1. Really nice article Ben!
    In Step 3, did you look into the possibility of assigning push access to AD groups instead of individual users? That would make it a lot easier to manage when the number of repositories grows.

    Regards, Daniel

    ReplyDelete
  2. @da9l

    From my (limited) understanding of the way things work, sadly I couldn't see a way to assign push access to Active Directory groups. The executable (CGI) doesn't [didn't at time of writing] seem to respect the AD privileges when it comes to writing to the directories. If you've got access to read/execute the CGI, then you've got access to write to the repository as long as the hgweb.config file is configured to allow your username to push.

    If you find a solution for this, I would dearly love to hear from you because I would certainly prefer to have it set up that way.

    Cheers and good luck!

    ReplyDelete
  3. Thank you for a nice tutorial. This is definitely great for most of the visitors.

    Which secure possibilities are there for efficient and secure "HG on windows" solution when one needs to deal with big binary files?

    Encryption/decryption causes load problems in server with HTTPS auth.

    ReplyDelete
  4. What about limiting the http verbs to certain types of user in the web.config. So for example allow GET to all and POST to developers?

    ReplyDelete
  5. Ben, I'm looking to limit push using active directory groups. Any more information you come across on that would be appreciated.

    ReplyDelete
  6. What if you get error 500 when you disable anonymous authentication? When I push I get that error.

    http auth: user brad, password ************
    sending: 0 kb
    sending: 0 kb
    abort: HTTP Error 500: Permission denied

    The credentials work when browsing the repository website. Pushing works when anonymous is turned on, but then you don't need a password to browse the website either.

    ReplyDelete
  7. The hgrc file is in the .hg/ folder of each repository, not the .hg/hgrc folder. So the file itself would be located at .hg/hgrc. I think that's what you meant, but you might want to clarify that.

    ReplyDelete