author | Martin Geisler <mg@lazybytes.net> |
Thu, 23 Jul 2009 00:01:24 +0200 | |
changeset 9201 | 3d6c9659886b |
parent 9052 | 1344e607180b |
child 9250 | 00986b9ed649 |
permissions | -rw-r--r-- |
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 | 33 |
# Check whether the source of incoming changes is in this list |
34 |
# ("serve" == ssh or http, "push", "pull", "bundle") |
|
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 | 42 |
# If acl.allow is not present, all users are allowed by default. |
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 | 48 |
# If acl.deny is not present, no users are refused by default. |
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 | 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 | 58 |
def buildmatch(ui, repo, user, key): |
59 |
'''return tuple of (match function, list enabled).''' |
|
60 |
if not ui.has_section(key): |
|
61 |
ui.debug(_('acl: %s not enabled\n') % key) |
|
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 | 64 |
pats = [pat for pat, users in ui.configitems(key) |
65 |
if user in users.replace(',', ' ').split()] |
|
66 |
ui.debug(_('acl: %s enabled, %d entries for user %s\n') % |
|
67 |
(key, len(pats), user)) |
|
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 | 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 | 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 | 90 |
cfg = ui.config('acl', 'config') |
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 | 93 |
allow = buildmatch(ui, repo, user, 'acl.allow') |
94 |
deny = buildmatch(ui, repo, user, 'acl.deny') |
|
95 |
||
96 |
for rev in xrange(repo[node], len(repo)): |
|
97 |
ctx = repo[rev] |
|
98 |
for f in ctx.files(): |
|
99 |
if deny and deny(f): |
|
100 |
ui.debug(_('acl: user %s denied on %s\n') % (user, f)) |
|
101 |
raise util.Abort(_('acl: access denied for changeset %s') % ctx) |
|
102 |
if allow and not allow(f): |
|
103 |
ui.debug(_('acl: user %s not allowed on %s\n') % (user, f)) |
|
104 |
raise util.Abort(_('acl: access denied for changeset %s') % ctx) |
|
105 |
ui.debug(_('acl: allowing changeset %s\n') % ctx) |