193 <para> |
193 <para> |
194 Root users can edit <literal>hgadmin</literal>, create new repositories and read and write to existing ones. Normal users cannot access <literal>hgadmin</literal> or create new repositories, but they can read and write to any other repository. This is only the default configuration; for more advanced configuration read <xref linkend="accesscontrol"/>. |
194 Root users can edit <literal>hgadmin</literal>, create new repositories and read and write to existing ones. Normal users cannot access <literal>hgadmin</literal> or create new repositories, but they can read and write to any other repository. This is only the default configuration; for more advanced configuration read <xref linkend="accesscontrol"/>. |
195 </para> |
195 </para> |
196 </section> |
196 </section> |
197 </section> |
197 </section> |
|
198 <section id="accesscontrol"> |
|
199 <title>Access control</title> |
|
200 <para> |
|
201 mercurial-server offers much more fine-grained access control than this division into two classes of users. Let's suppose you wish to give Pat access to the <literal>widget</literal> repository, but no other. We first copy Pat's SSH public key into the <filename |
|
202 class='directory'>keys/widget/pat</filename> directory in <literal>hgadmin</literal>. Now mercurial-server knows about Pat's key, but will give Pat no access to anything because the key is not under either <filename |
|
203 class='directory'>keys/root</filename> or <filename |
|
204 class='directory'>keys/users</filename>. To grant this key access, we must give mercurial-server a new access rule, so we create a file in <literal>hgadmin</literal> called <filename>access.conf</filename>, with the following contents:</para> |
|
205 <programlisting> |
|
206 write repo=widget user=widget/** |
|
207 </programlisting> |
|
208 <para> |
|
209 Pat will have read and write access as soon as we add, commit, and push these files. |
|
210 </para> |
|
211 <para> |
|
212 Each line of <filename>access.conf</filename> has the following syntax: |
|
213 </para> |
|
214 <programlisting> |
|
215 <replaceable>rule</replaceable> <replaceable>condition</replaceable> <replaceable>condition...</replaceable> |
|
216 </programlisting> |
|
217 <para> |
|
218 Blank lines and lines that start with <literal>#</literal> are ignored. Rule is one of |
|
219 </para> |
|
220 <itemizedlist> |
|
221 <listitem> |
|
222 <literal>init</literal>: allow reads, writes, and the creation of new repositories |
|
223 </listitem> |
|
224 <listitem> |
|
225 <literal>write</literal>: allow reads and writes |
|
226 </listitem> |
|
227 <listitem> |
|
228 <literal>read</literal>: allow only read operations |
|
229 </listitem> |
|
230 <listitem> |
|
231 <literal>deny</literal>: deny all requests |
|
232 </listitem> |
|
233 </itemizedlist> |
|
234 <para> |
|
235 When considering a request, mercurial-server steps through all the rules in <filename>/etc/mercurial-server/access.conf</filename> and then all the rules in <filename>access.conf</filename> in <literal>hgadmin</literal> looking for a rule which matches on every condition. If it does not find such a rule, it denies the request; otherwise it checks whether the rule grants sufficient privilege to allow it. |
|
236 </para> |
|
237 <para> |
|
238 By default, <filename>/etc/mercurial-server/access.conf</filename> has the following rules: |
|
239 </para> |
|
240 <programlisting> |
|
241 init user=root/** |
|
242 deny repo=hgadmin |
|
243 write user=users/** |
|
244 </programlisting> |
|
245 <para> |
|
246 These rules ensure that root users can do any operation on any repository, that no other users can access the <literal>hgadmin</literal> repository, and that those with keys in <filename class='directory'>keys/users</filename> can read or write to any repository but not create repositories. |
|
247 </para> |
|
248 <para> |
|
249 A condition is a globpattern matched against a relative path. The two most |
|
250 important conditions are |
|
251 </para> |
|
252 <itemizedlist> |
|
253 <listitem> |
|
254 <code><literal>user=</literal><replaceable>globpattern</replaceable></code>: path to the user's key |
|
255 </listitem> |
|
256 <listitem> |
|
257 <code><literal>repo=</literal><replaceable>globpattern</replaceable></code>: path to the repository |
|
258 </listitem> |
|
259 </itemizedlist> |
|
260 <para> |
|
261 "*" only matches one directory level, where "**" matches as many as you |
|
262 want. More precisely, "*" matches zero or more characters not including "/" |
|
263 while "**" matches zero or more characters including "/". |
|
264 </para> |
|
265 <section> |
|
266 <title>/etc/mercurial-server and hgadmin</title> |
|
267 <para> |
|
268 mercurial-server consults two distinct locations to collect information about what to allow: <filename |
|
269 class='directory'>/etc/mercurial-server</filename> and its own <literal>hgadmin</literal> repository. This is useful for several reasons: |
|
270 </para> |
|
271 <itemizedlist> |
|
272 <listitem> |
|
273 Users may not need the sophistication of access control via mercurial; for these users updating <filename |
|
274 class='directory'>/etc/mercurial-server</filename> may offer a simpler route. |
|
275 </listitem> |
|
276 <listitem> |
|
277 <filename |
|
278 class='directory'>/etc/mercurial-server</filename> is suitable for management by some other route, such as with <link |
|
279 xlink:href="http://reductivelabs.com/products/puppet">Puppet</link> |
|
280 </listitem> |
|
281 <listitem> |
|
282 If a change to <literal>hgadmin</literal> leaves you "locked out", <filename |
|
283 class='directory'>/etc/mercurial-server</filename> allows you a way back in. |
|
284 </listitem> |
|
285 <listitem> |
|
286 At install time, all users are "locked out", and so some mechanism to allow some users in is needed. |
|
287 </listitem> |
|
288 </itemizedlist> |
|
289 <para> |
|
290 Rules in <filename>/etc/mercurial-server/access.conf</filename> take precedence over those in <literal>hgadmin</literal>, and obviously keys in <filename class='directory'>/etc/mercurial-server/keys</filename> cannot be affected by changes to <literal>hgadmin</literal>. |
|
291 </para> |
|
292 <para> |
|
293 We anticipate that once mercurial-server is successfully installed and |
|
294 working most users will want to use <literal>hgadmin</literal> for most |
|
295 access control tasks. Once you have the right keys and |
|
296 <filename>access.conf</filename> set up in <literal>hgadmin</literal>, you |
|
297 can delete <filename>/etc/mercurial-server/access.conf</filename> and all |
|
298 of <filename class='directory'>/etc/mercurial-server/keys</filename>, |
|
299 turning control entirely over to <literal>hgadmin</literal>. |
|
300 </para> |
|
301 </section> |
|
302 <section> |
|
303 <title>File and branch conditions</title> |
|
304 <para> |
|
305 mercurial-server supports file and branch conditions, which restrict an |
|
306 operation depending on what files it modifies and what branch the work is |
|
307 on. </para> |
|
308 <caution> |
|
309 The way these conditions work is subtle and can be counterintuitive - if |
|
310 you want to keep things simple, stick to user and repo conditions, and then |
|
311 things are likely to work the way you would expect. |
|
312 </caution> |
|
313 <para> |
|
314 File and branch conditions are added to the conditions against which a rule |
|
315 matches, just like user and repo conditions; they have this form: |
|
316 </para> |
|
317 <itemizedlist> |
|
318 <listitem> |
|
319 <code><literal>file=</literal><replaceable>globpattern</replaceable></code>: file within the repo |
|
320 </listitem> |
|
321 <listitem> |
|
322 <code><literal>branch=</literal><replaceable>globpattern</replaceable></code>: Mercurial branch name |
|
323 </listitem> |
|
324 </itemizedlist> |
|
325 <para> |
|
326 However, in order to understand what effect adding these conditions will |
|
327 have, it helps to understand how and when these rules are applied. |
|
328 </para> |
|
329 <para> |
|
330 The rules file is used to make three decisions: |
|
331 </para> |
|
332 <itemizedlist> |
|
333 <listitem> |
|
334 Whether to allow a repository to be created |
|
335 </listitem> |
|
336 <listitem> |
|
337 Whether to allow any access to a repository |
|
338 </listitem> |
|
339 <listitem> |
|
340 Whether to allow a changeset, which is on a some branch |
|
341 </listitem> |
|
342 <listitem> |
|
343 Whether to allow a changeset which changes a particular file |
|
344 </listitem> |
|
345 </itemizedlist> |
|
346 <para> |
|
347 When the first two of these decisions are being made, nothing is known |
|
348 about what files might be changed, and so all file and branch conditions |
|
349 automatically succeed for the purpose of such decisions. This means that |
|
350 doing tricky things with file conditions can have counterintuitive |
|
351 consequences: |
|
352 </para> |
|
353 <itemizedlist> |
|
354 <listitem> |
|
355 <para>You cannot limit read access to a subset of a repository with a "read" |
|
356 rule and a file condition: any user who has access to a repository can read |
|
357 all of it and its full history. Such a rule can only have the effect of |
|
358 masking a later "write" rule, as in this example:</para> |
|
359 <programlisting> |
|
360 read repo=specialrepo file=dontwritethis |
|
361 write repo=specialrepo |
|
362 </programlisting> |
|
363 <para> |
|
364 allows all users to read specialrepo, and to write to all files |
|
365 <emphasis>except</emphasis> that any changeset which writes to |
|
366 <filename>dontwritethis</filename> will be rejected. |
|
367 </para> |
|
368 </listitem> |
|
369 <listitem> |
|
370 For similar reasons, don't give <literal>init</literal> rules file conditions. |
|
371 </listitem> |
|
372 <listitem> |
|
373 <para>Don't try to deny write access to a particular file on a particular |
|
374 branch - a developer can write to the file on another branch and then merge |
|
375 it in. Either deny all writes to the branch from that user, or allow them |
|
376 to write to all the files they can write to on any branch. In other words, |
|
377 something like this will have the intended effect: |
|
378 </para> |
|
379 <programlisting> |
|
380 write user=docs/* branch=docs file=docs/* |
|
381 </programlisting> |
|
382 <para> |
|
383 But something like this will not have the intended effect; it will |
|
384 effectively allow these users to write to any file on any branch, by |
|
385 writing it to "docs" first: |
|
386 </para> |
|
387 <programlisting> |
|
388 write user=docs/* branch=docs |
|
389 write user=docs/* file=docs/* |
|
390 read user=docs/* |
|
391 </programlisting> |
|
392 </listitem> |
|
393 </itemizedlist> |
|
394 </section> |
|
395 </section> |
198 <section> |
396 <section> |
199 <title>How mercurial-server works</title> |
397 <title>How mercurial-server works</title> |
200 <para> |
398 <para> |
201 All of the repositories controlled by mercurial-server are owned by a |
399 All of the repositories controlled by mercurial-server are owned by a |
202 single user, the <literal>hg</literal> user, which is why all URLs for |
400 single user, the <literal>hg</literal> user, which is why all URLs for |
221 <literal>hgadmin</literal> repository, creating an entry in |
419 <literal>hgadmin</literal> repository, creating an entry in |
222 <filename>~hg/.ssh/authorized_keys</filename> for each one. This is redone |
420 <filename>~hg/.ssh/authorized_keys</filename> for each one. This is redone |
223 automatically whenever a change is pushed to <literal>hgadmin</literal>. |
421 automatically whenever a change is pushed to <literal>hgadmin</literal>. |
224 </para> |
422 </para> |
225 </section> |
423 </section> |
226 <section id="accesscontrol"> |
|
227 <title>Access control</title> |
|
228 <para> |
|
229 mercurial-server offers much more fine-grained access control than this division into two classes of users. Let's suppose you wish to give Pat access to the <literal>widget</literal> repository, but no other. We first copy Pat's SSH public key into the <filename |
|
230 class='directory'>keys/widget/pat</filename> directory in <literal>hgadmin</literal>. Now mercurial-server knows about Pat's key, but will give Pat no access to anything because the key is not under either <filename |
|
231 class='directory'>keys/root</filename> or <filename |
|
232 class='directory'>keys/users</filename>. To grant this key access, we must give mercurial-server a new access rule, so we create a file in <literal>hgadmin</literal> called <filename>access.conf</filename>, with the following contents:</para> |
|
233 <programlisting> |
|
234 write repo=widget user=widget/** |
|
235 </programlisting> |
|
236 <para> |
|
237 Pat will have read and write access as soon as we add, commit, and push these files. |
|
238 </para> |
|
239 <para> |
|
240 Each line of <filename>access.conf</filename> has the following syntax: |
|
241 </para> |
|
242 <programlisting> |
|
243 <replaceable>rule</replaceable> <replaceable>condition</replaceable> <replaceable>condition...</replaceable> |
|
244 </programlisting> |
|
245 <para> |
|
246 Blank lines and lines that start with <literal>#</literal> are ignored. Rule is one of |
|
247 </para> |
|
248 <itemizedlist> |
|
249 <listitem> |
|
250 <literal>init</literal>: allow reads, writes, and the creation of new repositories |
|
251 </listitem> |
|
252 <listitem> |
|
253 <literal>write</literal>: allow reads and writes |
|
254 </listitem> |
|
255 <listitem> |
|
256 <literal>read</literal>: allow only read operations |
|
257 </listitem> |
|
258 <listitem> |
|
259 <literal>deny</literal>: deny all requests |
|
260 </listitem> |
|
261 </itemizedlist> |
|
262 <para> |
|
263 When considering a request, mercurial-server steps through all the rules in <filename>/etc/mercurial-server/access.conf</filename> and then all the rules in <filename>access.conf</filename> in <literal>hgadmin</literal> looking for a rule which matches on every condition. If it does not find such a rule, it denies the request; otherwise it checks whether the rule grants sufficient privilege to allow it. |
|
264 </para> |
|
265 <para> |
|
266 By default, <filename>/etc/mercurial-server/access.conf</filename> has the following rules: |
|
267 </para> |
|
268 <programlisting> |
|
269 init user=root/** |
|
270 deny repo=hgadmin |
|
271 write user=users/** |
|
272 </programlisting> |
|
273 <para> |
|
274 These rules ensure that root users can do any operation on any repository, that no other users can access the <literal>hgadmin</literal> repository, and that those with keys in <filename class='directory'>keys/users</filename> can read or write to any repository but not create repositories. |
|
275 </para> |
|
276 <para> |
|
277 A condition is a globpattern matched against a relative path. The two most |
|
278 important conditions are |
|
279 </para> |
|
280 <itemizedlist> |
|
281 <listitem> |
|
282 <code><literal>user=</literal><replaceable>globpattern</replaceable></code>: path to the user's key |
|
283 </listitem> |
|
284 <listitem> |
|
285 <code><literal>repo=</literal><replaceable>globpattern</replaceable></code>: path to the repository |
|
286 </listitem> |
|
287 </itemizedlist> |
|
288 <para> |
|
289 "*" only matches one directory level, where "**" matches as many as you |
|
290 want. More precisely, "*" matches zero or more characters not including "/" |
|
291 while "**" matches zero or more characters including "/". |
|
292 </para> |
|
293 <section> |
|
294 <title>/etc/mercurial-server and hgadmin</title> |
|
295 <para> |
|
296 mercurial-server consults two distinct locations to collect information about what to allow: <filename |
|
297 class='directory'>/etc/mercurial-server</filename> and its own <literal>hgadmin</literal> repository. This is useful for several reasons: |
|
298 </para> |
|
299 <itemizedlist> |
|
300 <listitem> |
|
301 Users may not need the sophistication of access control via mercurial; for these users updating <filename |
|
302 class='directory'>/etc/mercurial-server</filename> may offer a simpler route. |
|
303 </listitem> |
|
304 <listitem> |
|
305 <filename |
|
306 class='directory'>/etc/mercurial-server</filename> is suitable for management by some other route, such as with <link |
|
307 xlink:href="http://reductivelabs.com/products/puppet">Puppet</link> |
|
308 </listitem> |
|
309 <listitem> |
|
310 If a change to <literal>hgadmin</literal> leaves you "locked out", <filename |
|
311 class='directory'>/etc/mercurial-server</filename> allows you a way back in. |
|
312 </listitem> |
|
313 <listitem> |
|
314 At install time, all users are "locked out", and so some mechanism to allow some users in is needed. |
|
315 </listitem> |
|
316 </itemizedlist> |
|
317 <para> |
|
318 Rules in <filename>/etc/mercurial-server/access.conf</filename> take precedence over those in <literal>hgadmin</literal>, and obviously keys in <filename class='directory'>/etc/mercurial-server/keys</filename> cannot be affected by changes to <literal>hgadmin</literal>. |
|
319 </para> |
|
320 <para> |
|
321 We anticipate that once mercurial-server is successfully installed and |
|
322 working most users will want to use <literal>hgadmin</literal> for most |
|
323 access control tasks. Once you have the right keys and |
|
324 <filename>access.conf</filename> set up in <literal>hgadmin</literal>, you |
|
325 can delete <filename>/etc/mercurial-server/access.conf</filename> and all |
|
326 of <filename class='directory'>/etc/mercurial-server/keys</filename>, |
|
327 turning control entirely over to <literal>hgadmin</literal>. |
|
328 </para> |
|
329 </section> |
|
330 <section> |
|
331 <title>File and branch conditions</title> |
|
332 <para> |
|
333 mercurial-server supports file and branch conditions, which restrict an |
|
334 operation depending on what files it modifies and what branch the work is |
|
335 on. </para> |
|
336 <caution> |
|
337 The way these conditions work is subtle and can be counterintuitive - if |
|
338 you want to keep things simple, stick to user and repo conditions, and then |
|
339 things are likely to work the way you would expect. |
|
340 </caution> |
|
341 <para> |
|
342 File and branch conditions are added to the conditions against which a rule |
|
343 matches, just like user and repo conditions; they have this form: |
|
344 </para> |
|
345 <itemizedlist> |
|
346 <listitem> |
|
347 <code><literal>file=</literal><replaceable>globpattern</replaceable></code>: file within the repo |
|
348 </listitem> |
|
349 <listitem> |
|
350 <code><literal>branch=</literal><replaceable>globpattern</replaceable></code>: Mercurial branch name |
|
351 </listitem> |
|
352 </itemizedlist> |
|
353 <para> |
|
354 However, in order to understand what effect adding these conditions will |
|
355 have, it helps to understand how and when these rules are applied. |
|
356 </para> |
|
357 <para> |
|
358 The rules file is used to make three decisions: |
|
359 </para> |
|
360 <itemizedlist> |
|
361 <listitem> |
|
362 Whether to allow a repository to be created |
|
363 </listitem> |
|
364 <listitem> |
|
365 Whether to allow any access to a repository |
|
366 </listitem> |
|
367 <listitem> |
|
368 Whether to allow a changeset, which is on a some branch |
|
369 </listitem> |
|
370 <listitem> |
|
371 Whether to allow a changeset which changes a particular file |
|
372 </listitem> |
|
373 </itemizedlist> |
|
374 <para> |
|
375 When the first two of these decisions are being made, nothing is known |
|
376 about what files might be changed, and so all file and branch conditions |
|
377 automatically succeed for the purpose of such decisions. This means that |
|
378 doing tricky things with file conditions can have counterintuitive |
|
379 consequences: |
|
380 </para> |
|
381 <itemizedlist> |
|
382 <listitem> |
|
383 <para>You cannot limit read access to a subset of a repository with a "read" |
|
384 rule and a file condition: any user who has access to a repository can read |
|
385 all of it and its full history. Such a rule can only have the effect of |
|
386 masking a later "write" rule, as in this example:</para> |
|
387 <programlisting> |
|
388 read repo=specialrepo file=dontwritethis |
|
389 write repo=specialrepo |
|
390 </programlisting> |
|
391 <para> |
|
392 allows all users to read specialrepo, and to write to all files |
|
393 <emphasis>except</emphasis> that any changeset which writes to |
|
394 <filename>dontwritethis</filename> will be rejected. |
|
395 </para> |
|
396 </listitem> |
|
397 <listitem> |
|
398 For similar reasons, don't give <literal>init</literal> rules file conditions. |
|
399 </listitem> |
|
400 <listitem> |
|
401 <para>Don't try to deny write access to a particular file on a particular |
|
402 branch - a developer can write to the file on another branch and then merge |
|
403 it in. Either deny all writes to the branch from that user, or allow them |
|
404 to write to all the files they can write to on any branch. In other words, |
|
405 something like this will have the intended effect: |
|
406 </para> |
|
407 <programlisting> |
|
408 write user=docs/* branch=docs file=docs/* |
|
409 </programlisting> |
|
410 <para> |
|
411 But something like this will not have the intended effect; it will |
|
412 effectively allow these users to write to any file on any branch, by |
|
413 writing it to "docs" first: |
|
414 </para> |
|
415 <programlisting> |
|
416 write user=docs/* branch=docs |
|
417 write user=docs/* file=docs/* |
|
418 read user=docs/* |
|
419 </programlisting> |
|
420 </listitem> |
|
421 </itemizedlist> |
|
422 </section> |
|
423 </section> |
|
424 <section> |
424 <section> |
425 <title>Security</title> |
425 <title>Security</title> |
426 <para> |
426 <para> |
427 mercurial-server relies entirely on sshd to grant access to remote users. |
427 mercurial-server relies entirely on sshd to grant access to remote users. |
428 As a result, it runs no daemons, installs no setuid programs, and no part |
428 As a result, it runs no daemons, installs no setuid programs, and no part |