When setting up Mercurial to work with Active Directory (AD), you'll need to configure both authentication (who can access) and authorization (what they can do). The most common approach is through HTTP-based repositories with proper server configuration.
Apache Configuration Example
For Apache, you can use mod_auth_kerb for Kerberos authentication:
LoadModule auth_kerb_module modules/mod_auth_kerb.so
<Location /hg>
AuthType Kerberos
AuthName "Mercurial AD Authentication"
KrbMethodNegotiate On
KrbMethodK5Passwd On
KrbServiceName HTTP
KrbAuthRealms YOURDOMAIN.COM
Krb5Keytab /etc/apache2/http.keytab
Require valid-user
</Location>
To implement project-specific access control, you'll need to combine AD group membership checks with Mercurial's access control features. Here's how to set it up:
Using hgweb.config with AD Groups
[web]
allow_push = *
push_ssl = false
[hooks]
pretxnchangegroup.ad_auth = python:ad_auth.hook
[extensions]
hgsubversion =
acl =
Create a Python hook (ad_auth.py) to verify group membership:
import ldap
from mercurial import util
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
ldap_server = 'ldap://your-ad-server'
base_dn = 'DC=yourdomain,DC=com'
group_dn = 'CN=ProjectGroup,OU=Groups,DC=yourdomain,DC=com'
try:
conn = ldap.initialize(ldap_server)
conn.simple_bind_s()
user = os.environ.get('REMOTE_USER').split('@')[0]
filter = f'(memberOf:1.2.840.113556.1.4.1941:={group_dn})'
result = conn.search_s(base_dn, ldap.SCOPE_SUBTREE,
f'(&(objectClass=user)(sAMAccountName={user}){filter})')
if not result:
ui.warn(f'User {user} not in required AD group\n')
return True # Block the push
except Exception as e:
ui.warn(f'AD verification failed: {str(e)}\n')
return True
return False # Allow the push
For Windows environments using IIS, you can leverage Windows Authentication:
web.config Setup
<configuration>
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
</security>
<handlers>
<add name="Mercurial" path="*.hg" verb="*"
modules="IsapiModule" scriptProcessor="C:\path\to\hgwebdir.cgi"
resourceType="Unspecified" requireAccess="Script" />
</handlers>
</system.webServer>
</configuration>
For more complex scenarios, consider these additional approaches:
- Using RhgWeb (Mercurial plugin for IIS with AD support)
- Setting up a reverse proxy with NGINX handling AD authentication
- Implementing a custom WSGI middleware for authorization
The exact implementation will depend on your specific AD structure and security requirements, but these examples provide a solid foundation for integrating Mercurial with Active Directory authentication and group-based authorization.
When implementing Mercurial in an enterprise environment with Active Directory (AD), we need to address two critical security layers:
- Central Authentication: Verify user credentials against AD before granting any repository access
- Repository-Level Authorization: Control push/pull permissions based on AD group membership
The most robust solutions work with either Apache or IIS:
# Apache configuration example (httpd.conf)
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule ldap_module modules/mod_ldap.so
<Location /hg>
AuthType Basic
AuthName "Mercurial Repositories"
AuthBasicProvider ldap
AuthLDAPURL "ldap://domaincontroller:389/DC=domain,DC=com?sAMAccountName?sub?(objectClass=*)"
AuthLDAPBindDN "CN=binduser,CN=Users,DC=domain,DC=com"
AuthLDAPBindPassword "password"
Require valid-user
</Location>
For IIS implementation, we recommend using the IIS URL Authorization module with Windows Authentication:
# Web.config example for IIS
<configuration>
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
<authorization>
<add accessType="Allow" users="*" />
</authorization>
</security>
</system.webServer>
</configuration>
Using the hgweb.config
file to control repository access:
[web]
allow_push = ADGROUP\Developers
allow_read = ADGROUP\Developers, ADGROUP\QA
push_ssl = false
[hooks]
pretxnchangegroup.ad_auth = python:mercurialhooks.validate_ad_group
Create a custom hook (mercurialhooks.py
) to validate AD group membership:
import ldap
from mercurial import util
def validate_ad_group(ui, repo, **kwargs):
server = ldap.initialize('ldap://domaincontroller')
server.simple_bind_s('binduser@domain.com', 'password')
user = os.environ.get('REMOTE_USER')
if not user:
raise util.Abort('Authentication required')
groups = ['CN=Developers,OU=Groups,DC=domain,DC=com']
user_dn = get_user_dn(server, user)
if not check_membership(server, user_dn, groups):
raise util.Abort('User not authorized for this operation')
def get_user_dn(server, username):
result = server.search_s('DC=domain,DC=com',
ldap.SCOPE_SUBTREE,
'(sAMAccountName=%s)' % username,
['distinguishedName'])
return result[0][1]['distinguishedName'][0]
def check_membership(server, user_dn, allowed_groups):
for group in allowed_groups:
result = server.search_s(group,
ldap.SCOPE_BASE,
'(member=%s)' % user_dn)
if result:
return True
return False
- Always use SSL/TLS for LDAP connections (ldaps:// on port 636)
- Cache AD group memberships to reduce authentication overhead
- Implement proper error handling for AD connectivity issues
- Consider using Kerberos for single sign-on in Windows environments
Error | Solution |
---|---|
403 Forbidden | Verify AD group names and user membership |
LDAP bind failures | Check service account credentials and permissions |
Performance issues | Implement connection pooling for LDAP |