doc/manual.docbook
changeset 126 fd7ebe95d8e5
parent 125 fc5b8fc1040e
child 127 3262c0a53b59
equal deleted inserted replaced
125:fc5b8fc1040e 126:fd7ebe95d8e5
   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