annotate hgext/acl.py @ 9241:d98cef25b5af

Merge with crew-stable
author Martin Geisler <mg@lazybytes.net>
date Fri, 24 Jul 2009 15:28:29 +0200
parents 3d6c9659886b
children 00986b9ed649
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
1 # acl.py - changeset access control for mercurial
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
2 #
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8142
diff changeset
5 # This software may be used and distributed according to the terms of the
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8142
diff changeset
6 # GNU General Public License version 2, incorporated herein by reference.
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
7 #
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
8
8935
f4f0e902b750 extensions: change descriptions for hook-providing extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8894
diff changeset
9 '''hooks for controlling repository access
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
10
9052
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
11 This hook makes it possible to allow or deny write access to portions of a
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
12 repository when receiving incoming changesets.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
13
9052
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
14 The authorization is matched based on the local user name on the system where
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
15 the hook runs, and not the committer of the original changeset (since the
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
16 latter is merely informative).
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
17
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
18 The acl hook is best used along with a restricted shell like hgsh, preventing
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
19 authenticating users from doing anything other than pushing or pulling. The
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
20 hook is not safe to use if users have interactive shell access, as they can
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
21 then disable the hook. Nor is it safe if remote users share an account,
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
22 because then there is no way to distinguish them.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
23
9201
3d6c9659886b acl: use reST syntax for literal blocks
Martin Geisler <mg@lazybytes.net>
parents: 9052
diff changeset
24 To use this hook, configure the acl extension in your hgrc like this::
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
25
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
26 [extensions]
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
27 hgext.acl =
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
28
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
29 [hooks]
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
30 pretxnchangegroup.acl = python:hgext.acl.hook
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
31
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
32 [acl]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
33 # Check whether the source of incoming changes is in this list
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
34 # ("serve" == ssh or http, "push", "pull", "bundle")
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
35 sources = serve
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
36
9052
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
37 The allow and deny sections take a subtree pattern as key (with a glob syntax
1344e607180b acl: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9018
diff changeset
38 by default), and a comma separated list of users as the corresponding value.
9201
3d6c9659886b acl: use reST syntax for literal blocks
Martin Geisler <mg@lazybytes.net>
parents: 9052
diff changeset
39 The deny list is checked before the allow list is. ::
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
40
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
41 [acl.allow]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
42 # If acl.allow is not present, all users are allowed by default.
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
43 # An empty acl.allow section means no users allowed.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
44 docs/** = doc_writer
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
45 .hgtags = release_engineer
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
46
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
47 [acl.deny]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
48 # If acl.deny is not present, no users are refused by default.
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
49 # An empty acl.deny section means all users allowed.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
50 glob pattern = user4, user5
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
51 ** = user6
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
52 '''
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
53
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
54 from mercurial.i18n import _
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
55 from mercurial import util, match
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
56 import getpass, urllib
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
57
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
58 def buildmatch(ui, repo, user, key):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
59 '''return tuple of (match function, list enabled).'''
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
60 if not ui.has_section(key):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
61 ui.debug(_('acl: %s not enabled\n') % key)
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
62 return None
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
63
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
64 pats = [pat for pat, users in ui.configitems(key)
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
65 if user in users.replace(',', ' ').split()]
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
66 ui.debug(_('acl: %s enabled, %d entries for user %s\n') %
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
67 (key, len(pats), user))
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
68 if pats:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
69 return match.match(repo.root, '', pats)
8682
cc7da5aae4cd match: remove match.never
Matt Mackall <mpm@selenic.com>
parents: 8567
diff changeset
70 return match.exact(repo.root, '', [])
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
71
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
72
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
73 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
74 if hooktype != 'pretxnchangegroup':
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
75 raise util.Abort(_('config error - hook type "%s" cannot stop '
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
76 'incoming changesets') % hooktype)
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
77 if source not in ui.config('acl', 'sources', 'serve').split():
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
78 ui.debug(_('acl: changes have source "%s" - skipping\n') % source)
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
79 return
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
80
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
81 user = None
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
82 if source == 'serve' and 'url' in kwargs:
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
83 url = kwargs['url'].split(':')
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
84 if url[0] == 'remote' and url[1].startswith('http'):
9018
5ed463d0ebdb acl: read correct index into url for username (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8935
diff changeset
85 user = urllib.unquote(url[3])
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
86
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
87 if user is None:
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
88 user = getpass.getuser()
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
89
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
90 cfg = ui.config('acl', 'config')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
91 if cfg:
8142
912bfef12ba6 ui: fold readsections into readconfig
Matt Mackall <mpm@selenic.com>
parents: 6766
diff changeset
92 ui.readconfig(cfg, sections = ['acl.allow', 'acl.deny'])
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
93 allow = buildmatch(ui, repo, user, 'acl.allow')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
94 deny = buildmatch(ui, repo, user, 'acl.deny')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
95
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
96 for rev in xrange(repo[node], len(repo)):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
97 ctx = repo[rev]
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
98 for f in ctx.files():
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
99 if deny and deny(f):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
100 ui.debug(_('acl: user %s denied on %s\n') % (user, f))
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
101 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
102 if allow and not allow(f):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
103 ui.debug(_('acl: user %s not allowed on %s\n') % (user, f))
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
104 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
105 ui.debug(_('acl: allowing changeset %s\n') % ctx)