##// END OF EJS Templates
acl: updated doc string to reflect recent changes
Elifarley Callado Coelho Cruz -
r11042:d82f3651 default
parent child Browse files
Show More
@@ -1,121 +1,162 b''
1 1 # acl.py - changeset access control for mercurial
2 2 #
3 3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''hooks for controlling repository access
9 9
10 10 This hook makes it possible to allow or deny write access to portions
11 of a repository when receiving incoming changesets.
11 of a repository when receiving incoming changesets via pretxnchangegroup and
12 pretxncommit.
12 13
13 14 The authorization is matched based on the local user name on the
14 15 system where the hook runs, and not the committer of the original
15 16 changeset (since the latter is merely informative).
16 17
17 18 The acl hook is best used along with a restricted shell like hgsh,
18 19 preventing authenticating users from doing anything other than
19 20 pushing or pulling. The hook is not safe to use if users have
20 21 interactive shell access, as they can then disable the hook.
21 22 Nor is it safe if remote users share an account, because then there
22 23 is no way to distinguish them.
23 24
24 To use this hook, configure the acl extension in your hgrc like this::
25 The deny list is checked before the allow list is.
26
27 The allow and deny sections take key-value pairs, having a subtree pattern
28 as key (with a glob syntax by default). The corresponding value can be either:
29 1) an asterisk, to match everyone;
30 2) a comma-separated list containing users and groups.
31
32 Group names must be prefixed with an @ symbol.
33 Specifying a group name has the same effect as specifying all the users in
34 that group.
35 The set of users for a group is taken from "grp.getgrnam"
36 (see http://docs.python.org/library/grp.html#grp.getgrnam).
37
38 To use this hook, configure the acl extension in your hgrc like this:
25 39
26 40 [extensions]
27 41 acl =
28 42
29 43 [hooks]
44
45 # Use this if you want to check access restrictions at commit time
46 pretxncommit.acl = python:hgext.acl.hook
47
48 # Use this if you want to check access restrictions for pull, push, bundle
49 # and serve.
30 50 pretxnchangegroup.acl = python:hgext.acl.hook
31 51
32 52 [acl]
33 53 # Check whether the source of incoming changes is in this list
34 54 # ("serve" == ssh or http, "push", "pull", "bundle")
35 55 sources = serve
36 56
37 The allow and deny sections take a subtree pattern as key (with a glob
38 syntax by default), and a comma separated list of users as the
39 corresponding value. The deny list is checked before the allow list
40 is. ::
57 [acl.deny]
58 # This list is checked first. If a match is found, 'acl.allow' will not be
59 # checked.
60 # if acl.deny is not present, no users denied by default
61 # empty acl.deny = all users allowed
62 # Format for both lists: glob pattern = user4, user5, @group1
63
64 # To match everyone, use an asterisk for the user:
65 # my/glob/pattern = *
66
67 # user6 will not have write access to any file:
68 ** = user6
69
70 # Group "hg-denied" will not have write access to any file:
71 ** = @hg-denied
72
73 # Nobody will be able to change "DONT-TOUCH-THIS.txt", despite everyone being
74 # able to change all other files. See below.
75 src/main/resources/DONT-TOUCH-THIS.txt = *
41 76
42 77 [acl.allow]
43 # If acl.allow is not present, all users are allowed by default.
44 # An empty acl.allow section means no users allowed.
78 # if acl.allow not present, all users allowed by default
79 # empty acl.allow = no users allowed
80
81 # User "doc_writer" has write access to any file under the "docs" folder:
45 82 docs/** = doc_writer
83
84 # User "jack" and group "designers" have write access to any file under the
85 # "images" folder:
86 images/** = jack, @designers
87
88 # Everyone (except for "user6" - see "acl.deny" above) will have write access
89 to any file under the "resources" folder (except for 1 file. See "acl.deny"):
90 src/main/resources/** = *
91
46 92 .hgtags = release_engineer
47 93
48 [acl.deny]
49 # If acl.deny is not present, no users are refused by default.
50 # An empty acl.deny section means all users allowed.
51 glob pattern = user4, user5
52 ** = user6
53 94 '''
54 95
55 96 from mercurial.i18n import _
56 97 from mercurial import util, match
57 98 import getpass, urllib, grp
58 99
59 100 def _getusers(group):
60 101 return grp.getgrnam(group).gr_mem
61 102
62 103 def _usermatch(user, usersorgroups):
63 104
64 105 if usersorgroups == '*':
65 106 return True
66 107
67 108 for ug in usersorgroups.replace(',', ' ').split():
68 109 if user == ug or ug.find('@') == 0 and user in _getusers(ug[1:]):
69 110 return True
70 111
71 112 return False
72 113
73 114 def buildmatch(ui, repo, user, key):
74 115 '''return tuple of (match function, list enabled).'''
75 116 if not ui.has_section(key):
76 117 ui.debug('acl: %s not enabled\n' % key)
77 118 return None
78 119
79 120 pats = [pat for pat, users in ui.configitems(key)
80 121 if _usermatch(user, users)]
81 122 ui.debug('acl: %s enabled, %d entries for user %s\n' %
82 123 (key, len(pats), user))
83 124 if pats:
84 125 return match.match(repo.root, '', pats)
85 126 return match.exact(repo.root, '', [])
86 127
87 128
88 129 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
89 130 if hooktype not in ['pretxnchangegroup', 'pretxncommit']:
90 131 raise util.Abort(_('config error - hook type "%s" cannot stop '
91 132 'incoming changesets nor commits') % hooktype)
92 133 if (hooktype == 'pretxnchangegroup' and
93 134 source not in ui.config('acl', 'sources', 'serve').split()):
94 135 ui.debug('acl: changes have source "%s" - skipping\n' % source)
95 136 return
96 137
97 138 user = None
98 139 if source == 'serve' and 'url' in kwargs:
99 140 url = kwargs['url'].split(':')
100 141 if url[0] == 'remote' and url[1].startswith('http'):
101 142 user = urllib.unquote(url[3])
102 143
103 144 if user is None:
104 145 user = getpass.getuser()
105 146
106 147 cfg = ui.config('acl', 'config')
107 148 if cfg:
108 149 ui.readconfig(cfg, sections = ['acl.allow', 'acl.deny'])
109 150 allow = buildmatch(ui, repo, user, 'acl.allow')
110 151 deny = buildmatch(ui, repo, user, 'acl.deny')
111 152
112 153 for rev in xrange(repo[node], len(repo)):
113 154 ctx = repo[rev]
114 155 for f in ctx.files():
115 156 if deny and deny(f):
116 157 ui.debug('acl: user %s denied on %s\n' % (user, f))
117 158 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
118 159 if allow and not allow(f):
119 160 ui.debug('acl: user %s not allowed on %s\n' % (user, f))
120 161 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
121 162 ui.debug('acl: allowing changeset %s\n' % ctx)
General Comments 0
You need to be logged in to leave comments. Login now