|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en" |
|
3 xmlns:xlink="http://www.w3.org/1999/xlink"> |
|
4 <info> |
|
5 <title>Sharing Mercurial repositories with mercurial-server</title> |
|
6 <author><firstname>Paul</firstname><surname>Crowley</surname></author> |
|
7 <copyright><year>2009</year><holder>Paul Crowley, LShift Ltd</holder></copyright> |
|
8 </info> |
|
9 <section> |
|
10 <title>About mercurial-server</title> |
|
11 <para> |
|
12 Home page: <link xlink:href="http://www.lshift.net/mercurial-server.html"/> |
|
13 </para> |
|
14 <para> |
|
15 mercurial-server gives your developers remote read/write access to |
|
16 centralized <link xlink:href="http://hg-scm.org/">Mercurial</link> |
|
17 repositories using SSH public key authentication; it provides convenient |
|
18 and fine-grained key management and access control. |
|
19 </para> |
|
20 <para> |
|
21 Though mercurial-server is currently targeted at Debian-based systems such |
|
22 as Ubuntu, other users have reported success getting it running on other |
|
23 Unix-based systems such as Red Hat. Running it on a non-Unix system such as |
|
24 Windows is not supported. You will need root privileges to install it. |
|
25 </para> |
|
26 </section> |
|
27 <section> |
|
28 <title>Step by step</title> |
|
29 <para> |
|
30 mercurial-server authenticates users not using passwords but using SSH |
|
31 public keys; everyone who wants access to a mercurial-server repository |
|
32 will need such a key. In combination with <command>ssh-agent</command> (or |
|
33 equivalents such as the Windows program <link |
|
34 xlink:href="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">Pageant</link>), |
|
35 this means that users will not need to type in a password to access the |
|
36 repository. If you're not familiar with SSH public keys, the <link |
|
37 xlink:href="http://sial.org/howto/openssh/publickey-auth/">OpenSSH Public |
|
38 Key Authentication tutorial</link> may be helpful. |
|
39 </para> |
|
40 <section> |
|
41 <title>Installing mercurial-server</title> |
|
42 <para> |
|
43 In what follows, we assume that your username is <systemitem |
|
44 class="username">jay</systemitem>, that you usually sit at a machine called |
|
45 <systemitem class="systemname">spoon</systemitem> and you wish to |
|
46 install mercurial-server on <systemitem |
|
47 class="systemname">jeeves</systemitem>. We assume that you have created your SSH public key, set up your SSH agent with this key, and that this key gives you access to <systemitem |
|
48 class="systemname">jeeves</systemitem>. |
|
49 </para> |
|
50 <para>First install mercurial-server on <systemitem |
|
51 class="systemname">jeeves</systemitem>:</para> |
|
52 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>scp mercurial-server_0.6.1_amd64.deb jeeves:</userinput> |
|
53 <computeroutput>mercurial-server_0.6.1_amd64.deb 100% |
|
54 jay@spoon:~$ </computeroutput><userinput>ssh -A jeeves</userinput> |
|
55 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo dpkg -i mercurial-server_0.6.1_amd64.deb</userinput> |
|
56 <computeroutput>[sudo] password for jay: |
|
57 Selecting previously deselected package mercurial-server. |
|
58 (Reading database ... 144805 files and directories currently installed.) |
|
59 Unpacking mercurial-server (from .../mercurial-server_0.6.1_amd64.deb) ... |
|
60 Setting up mercurial-server (0.6.1) ... |
|
61 jay@jeeves:~$ </computeroutput></screen> |
|
62 <para> |
|
63 mercurial-server is now installed on the repository host. Next, we need to give you permission to access its repositories. |
|
64 </para> |
|
65 <screen><computeroutput>jay@jeeves:~$ </computeroutput><userinput>ssh-add -L > my-key</userinput> |
|
66 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo mkdir -p /etc/mercurial-server/keys/root/jay</userinput> |
|
67 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo cp my-key /etc/mercurial-server/keys/root/jay/spoon</userinput> |
|
68 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput> |
|
69 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>exit</userinput> |
|
70 <computeroutput>Connection to jeeves closed. |
|
71 jay@spoon:~$ </computeroutput></screen> |
|
72 <para> |
|
73 You can now create repositories on the remote machine and have complete |
|
74 read-write access to all of them. |
|
75 </para> |
|
76 </section> |
|
77 <section> |
|
78 <title>Creating repositories</title> |
|
79 <para> |
|
80 To store a repository on the server, clone it over. |
|
81 </para> |
|
82 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>cd myproj</userinput> |
|
83 <computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>hg clone . ssh://hg@jeeves/jays/project</userinput> |
|
84 <computeroutput>searching for changes |
|
85 remote: adding changesets |
|
86 remote: adding manifests |
|
87 remote: adding file changes |
|
88 remote: added 119 changesets with 284 changes to 61 files |
|
89 jay@spoon:~/myproj$ </computeroutput><userinput>hg pull ssh://hg@jeeves/jays/project</userinput> |
|
90 <computeroutput>pulling from ssh://hg@jeeves/jays/project |
|
91 searching for changes |
|
92 no changes found |
|
93 <computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>cd ..</userinput> |
|
94 jay@spoon:~$ </computeroutput></screen> |
|
95 </section> |
|
96 <section> |
|
97 <title>Adding other users</title> |
|
98 <para> |
|
99 At this stage, no-one but you has any access to any repositories you |
|
100 create on this system. In order to give anyone else access, you'll need a |
|
101 copy of their SSH public key; we'll assume you have that key in |
|
102 <filename>~/sam-saucer-key.pub</filename>. To manage access, you make changes to the special <filename |
|
103 class='directory'>hgadmin</filename> repository. |
|
104 </para> |
|
105 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>hg clone ssh://hg@jeeves/hgadmin</userinput> |
|
106 <computeroutput>destination directory: hgadmin |
|
107 no changes found |
|
108 updating working directory |
|
109 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
110 jay@spoon:~$ </computeroutput><userinput>cd hgadmin</userinput> |
|
111 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>mkdir -p keys/users/sam</userinput> |
|
112 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>cp ~/sam-saucer-key.pub keys/users/sam/saucer</userinput> |
|
113 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg add</userinput> |
|
114 <computeroutput>adding keys/users/sam/saucer |
|
115 jay@spoon:~/hgadmin$ </computeroutput><userinput>hg commit -m "Add Sam's key"</userinput> |
|
116 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg push</userinput> |
|
117 <computeroutput>pushing to ssh://hg@jeeves/hgadmin |
|
118 searching for changes |
|
119 remote: adding changesets |
|
120 remote: adding manifests |
|
121 remote: adding file changes |
|
122 remote: added 1 changesets with 1 changes to 1 files |
|
123 jay@spoon:~/hgadmin$ </computeroutput></screen> |
|
124 <para> |
|
125 Sam can now read and write to your |
|
126 <uri>ssh://hg@jeeves/jays/project</uri> repository. |
|
127 Most other changes to access control can be made simply by making and |
|
128 pushing changes to <filename |
|
129 class='directory'>hgadmin</filename>, and you can use Mercurial to |
|
130 cooperate with other root users in the normal way. |
|
131 </para> |
|
132 <para> |
|
133 If you prefer, you could give them access by |
|
134 logging into <systemitem class="systemname">jeeves</systemitem>, |
|
135 putting the key in the right place under <filename |
|
136 class='directory'>/etc/mercurial-server/keys</filename>, and re-running |
|
137 <userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput>. |
|
138 However, using <filename |
|
139 class='directory'>hgadmin</filename> is usually more convenient if you need to make more than a very few changes; it also makes it easier to share administration with others and provides a log of all changes. |
|
140 </para> |
|
141 </section> |
|
142 </section> |
|
143 <section> |
|
144 <title>Access control</title> |
|
145 <para> |
|
146 Out of the box, mercurial-server supports two kinds of users: "root" users and normal users. If you followed the steps above, you are a "root" user because your key is under <filename class='directory'>keys/root</filename>, while the other user you gave access to is a normal user since their key is under <filename class='directory'>keys/users</filename>. Keys that are not in either of these directories will by default have no access to anything. |
|
147 </para> |
|
148 <para> |
|
149 Root users can edit <filename |
|
150 class='directory'>hgadmin</filename>, create new repositories and read and write to existing ones. Normal users cannot access <filename |
|
151 class='directory'>hgadmin</filename> or create new repositories, but they can read and write to any other repository. |
|
152 </para> |
|
153 <section> |
|
154 <title>Using access.conf</title> |
|
155 <para> |
|
156 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 <filename |
|
157 class='directory'>widget</filename> repository, but no other. We first copy Pat's SSH public key into the <filename |
|
158 class='directory'>keys/pat</filename> directory in <filename |
|
159 class='directory'>hgadmin</filename>. This tells mercurial-server about Pat's key, but gives Pat no access to anything because the key is not under either <filename |
|
160 class='directory'>keys/root</filename> or <filename |
|
161 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 <filename |
|
162 class='directory'>hgadmin</filename> called <filename>access.conf</filename>, with the following contents:</para> |
|
163 <programlisting># Give Pat access to the "widget" repository |
|
164 write repo=widget user=pat |
|
165 </programlisting> |
|
166 <para> |
|
167 Pat will have read and write access to the <filename |
|
168 class='directory'>widget</filename> repository as soon as we add, commit, and push these files. |
|
169 </para> |
|
170 <para> |
|
171 Each line of <filename>access.conf</filename> has the following syntax: |
|
172 </para> |
|
173 <programlisting><replaceable>rule</replaceable> <replaceable>condition</replaceable> <replaceable>condition...</replaceable> |
|
174 </programlisting> |
|
175 <para> |
|
176 Blank lines and lines that start with <code>#</code> are ignored. Rule is |
|
177 one of |
|
178 </para> |
|
179 <itemizedlist> |
|
180 <listitem> |
|
181 <literal>init</literal>: allow reads, writes, and the creation of new repositories |
|
182 </listitem> |
|
183 <listitem> |
|
184 <literal>write</literal>: allow reads and writes |
|
185 </listitem> |
|
186 <listitem> |
|
187 <literal>read</literal>: allow only read operations |
|
188 </listitem> |
|
189 <listitem> |
|
190 <literal>deny</literal>: deny all requests |
|
191 </listitem> |
|
192 </itemizedlist> |
|
193 <para> |
|
194 A condition is a globpattern matched against a relative path. The two most |
|
195 important conditions are |
|
196 </para> |
|
197 <itemizedlist> |
|
198 <listitem> |
|
199 <code>user=<replaceable>globpattern</replaceable></code>: path to the user's key |
|
200 </listitem> |
|
201 <listitem> |
|
202 <code>repo=<replaceable>globpattern</replaceable></code>: path to the repository |
|
203 </listitem> |
|
204 </itemizedlist> |
|
205 <para> |
|
206 <code>*</code> only matches one directory level, where <code>**</code> |
|
207 matches as many as you want. More precisely, <code>*</code> matches zero or |
|
208 more characters not including <code>/</code> while <code>**</code> matches |
|
209 zero or more characters including <code>/</code>. So |
|
210 <code>projects/*</code> matches <filename |
|
211 class='directory'>projects/foo</filename> but not <filename |
|
212 class='directory'>projects/foo/bar</filename>, while |
|
213 <code>projects/**</code> matches both. |
|
214 </para> |
|
215 <para> |
|
216 When considering a request, mercurial-server steps through all the rules in |
|
217 <filename>/etc/mercurial-server/access.conf</filename> and then all the |
|
218 rules in <filename>access.conf</filename> in <filename |
|
219 class='directory'>hgadmin</filename> |
|
220 looking for a rule which matches on every condition. The first match |
|
221 determines whether the request will be allowed; if there is no match in |
|
222 either file, the request will be denied. |
|
223 </para> |
|
224 <para> |
|
225 By default, <filename>/etc/mercurial-server/access.conf</filename> has the |
|
226 following rules: |
|
227 </para> |
|
228 <programlisting>init user=root/** |
|
229 deny repo=hgadmin |
|
230 write user=users/** |
|
231 </programlisting> |
|
232 <para> |
|
233 These rules ensure that root users can do any operation on any repository, |
|
234 that no other users can access the <filename |
|
235 class='directory'>hgadmin</filename> repository, |
|
236 and that those with keys in <filename |
|
237 class='directory'>keys/users</filename> can read or write to any repository |
|
238 but not create repositories. Some examples of how these rules work: |
|
239 </para> |
|
240 <itemizedlist> |
|
241 <listitem> |
|
242 User <filename class='directory'>root/jay</filename> creates a repository |
|
243 <filename class='directory'>foo/bar/baz</filename>. This matches the first |
|
244 rule and so will be allowed. |
|
245 </listitem> |
|
246 <listitem> |
|
247 User <filename class='directory'>root/jay</filename> changes repository |
|
248 <filename class='directory'>hgadmin</filename>. Again, this matches the |
|
249 first rule and so will be allowed; later rules have no effect. |
|
250 </listitem> |
|
251 <listitem> |
|
252 User <filename class='directory'>users/sam</filename> tries to read |
|
253 repository <filename class='directory'>hgadmin</filename>. This does not |
|
254 match the first rule, but matches the second, and so will be denied. |
|
255 </listitem> |
|
256 <listitem> |
|
257 User <filename class='directory'>users/sam</filename> tries to create |
|
258 repository <filename class='directory'>sams-project</filename>. This does |
|
259 not match the first two rules, but matches the third; this is a |
|
260 <literal>write</literal> rule, which doesn't grant the privilege to create |
|
261 repositories, so the request will be denied. |
|
262 </listitem> |
|
263 <listitem> |
|
264 User <filename class='directory'>users/sam</filename> writes to existing |
|
265 repository <filename class='directory'>projects/main</filename>. Again, |
|
266 this matches the third rule, which allows the request. |
|
267 </listitem> |
|
268 <listitem> |
|
269 User <filename class='directory'>pat</filename> tries to write to existing |
|
270 repository <filename class='directory'>widget</filename>. Until we change |
|
271 the <filename>access.conf</filename> file in <filename |
|
272 class='directory'>hgadmin</filename>, this will match no rule, and so will |
|
273 be denied. |
|
274 </listitem> |
|
275 <listitem> |
|
276 Any request from a user whose key not under the <filename |
|
277 class='directory'>keys</filename> directory at all will always be denied, |
|
278 no matter what rules are in effect; because of the way SSH authentication |
|
279 works, they will be prompted to enter a password, but no password will |
|
280 work. This can't be changed. |
|
281 </listitem> |
|
282 </itemizedlist> |
|
283 </section> |
|
284 <section> |
|
285 <title>/etc/mercurial-server and hgadmin</title> |
|
286 <para> |
|
287 mercurial-server consults two distinct locations to collect information about what to allow: <filename |
|
288 class='directory'>/etc/mercurial-server</filename> and its own <filename |
|
289 class='directory'>hgadmin</filename> repository. This is useful for several reasons: |
|
290 </para> |
|
291 <itemizedlist> |
|
292 <listitem> |
|
293 Some users may not need the convenience of access control via mercurial; for these users updating <filename |
|
294 class='directory'>/etc/mercurial-server</filename> may offer a simpler route. |
|
295 </listitem> |
|
296 <listitem> |
|
297 <filename class='directory'>/etc/mercurial-server</filename> is suitable |
|
298 for management with tools such as <link |
|
299 xlink:href="http://reductivelabs.com/products/puppet">Puppet</link> |
|
300 </listitem> |
|
301 <listitem> |
|
302 If a change to <filename |
|
303 class='directory'>hgadmin</filename> leaves you "locked out", <filename |
|
304 class='directory'>/etc/mercurial-server</filename> allows you a way back in. |
|
305 </listitem> |
|
306 <listitem> |
|
307 At install time, all users are "locked out", and so some mechanism to allow some users in is needed. |
|
308 </listitem> |
|
309 </itemizedlist> |
|
310 <para> |
|
311 Rules in <filename>/etc/mercurial-server/access.conf</filename> are checked before those in <filename |
|
312 class='directory'>hgadmin</filename>, and keys in <filename class='directory'>/etc/mercurial-server/keys</filename> will be present no matter how <filename |
|
313 class='directory'>hgadmin</filename> changes. |
|
314 </para> |
|
315 <para> |
|
316 We anticipate that once mercurial-server is successfully installed and |
|
317 working you will usually want to use <filename |
|
318 class='directory'>hgadmin</filename> for most |
|
319 access control tasks. Once you have the right keys and |
|
320 <filename>access.conf</filename> set up in <filename |
|
321 class='directory'>hgadmin</filename>, you |
|
322 can delete <filename>/etc/mercurial-server/access.conf</filename> and all |
|
323 of <filename class='directory'>/etc/mercurial-server/keys</filename>, |
|
324 turning control entirely over to <filename |
|
325 class='directory'>hgadmin</filename>. |
|
326 </para> |
|
327 <para> |
|
328 <filename>/etc/mercurial-server/remote-hgrc</filename> is in the |
|
329 <systemitem>HGRCPATH</systemitem> for all remote access to mercurial-server |
|
330 repositories. This file contains the hooks that mercurial-server uses for |
|
331 access control and logging. You can add hooks to this file, but obviously |
|
332 breaking the existing hooks will disable the relevant functionality and |
|
333 isn't advisable. |
|
334 </para> |
|
335 </section> |
|
336 <section> |
|
337 <title>File and branch conditions</title> |
|
338 <para> |
|
339 mercurial-server supports file and branch conditions, which restrict an |
|
340 operation depending on what files it modifies and what branch the work is |
|
341 on. </para> |
|
342 <caution> |
|
343 The way these conditions work is subtle and can be counterintuitive. Unless |
|
344 you need what they provide, ignore this section, stick to user and repo |
|
345 conditions, and then things are likely to work the way you would expect. If |
|
346 you do need what they provide, read what follows very carefully. |
|
347 </caution> |
|
348 <para> |
|
349 File and branch conditions are added to the conditions against which a rule |
|
350 matches, just like user and repo conditions; they have this form: |
|
351 </para> |
|
352 <itemizedlist> |
|
353 <listitem> |
|
354 <code>file=<replaceable>globpattern</replaceable></code>: file within the repo |
|
355 </listitem> |
|
356 <listitem> |
|
357 <code>branch=<replaceable>globpattern</replaceable></code>: Mercurial branch name |
|
358 </listitem> |
|
359 </itemizedlist> |
|
360 <para> |
|
361 However, in order to understand what effect adding these conditions will |
|
362 have, it helps to understand how and when these rules are applied. |
|
363 </para> |
|
364 <para> |
|
365 The rules file is used to make three decisions: |
|
366 </para> |
|
367 <itemizedlist> |
|
368 <listitem> |
|
369 Whether to allow a repository to be created |
|
370 </listitem> |
|
371 <listitem> |
|
372 Whether to allow any access to a repository |
|
373 </listitem> |
|
374 <listitem> |
|
375 Whether to allow a changeset |
|
376 </listitem> |
|
377 </itemizedlist> |
|
378 <para> |
|
379 When the first two of these decisions are being made, nothing is known |
|
380 about any changsets that might be pushed, and so all file and branch |
|
381 conditions automatically succeed for the purpose of such decisions. For the |
|
382 third condition, every file changed in the changeset must be allowed by a |
|
383 <literal>write</literal> or <literal>init</literal> rule for the changeset |
|
384 to be allowed. |
|
385 </para> |
|
386 <para> |
|
387 This means that doing tricky things with file conditions can have |
|
388 counterintuitive consequences: |
|
389 </para> |
|
390 <itemizedlist> |
|
391 <listitem> |
|
392 <para>You cannot limit read access to a subset of a repository with a <literal>read</literal> |
|
393 rule and a file condition: any user who has access to a repository can read |
|
394 all of it and its full history. Such a rule can only have the effect of |
|
395 masking a later <literal>write</literal> rule, as in this example:</para> |
|
396 <programlisting>read repo=specialrepo file=dontwritethis |
|
397 write repo=specialrepo |
|
398 </programlisting> |
|
399 <para> |
|
400 allows all users to read <literal>specialrepo</literal>, and to write to all files |
|
401 <emphasis>except</emphasis> that any changeset which writes to |
|
402 <filename>dontwritethis</filename> will be rejected. |
|
403 </para> |
|
404 </listitem> |
|
405 <listitem> |
|
406 For similar reasons, don't give <literal>init</literal> rules file conditions. |
|
407 </listitem> |
|
408 <listitem> |
|
409 <para>Don't try to deny write access to a particular file on a particular |
|
410 branch—a developer can write to the file on another branch and then merge |
|
411 it in. Either deny all writes to the branch from that user, or allow them |
|
412 to write to all the files they can write to on any branch. |
|
413 </para> |
|
414 <programlisting>write user=docs/* branch=docs file=docs/* |
|
415 </programlisting> |
|
416 <para> |
|
417 This rule grants users whose keys are in the <filename |
|
418 class='directory'>docs</filename> subdirectory the power to push changesets |
|
419 into any repository only if those changesets are on the |
|
420 <literal>docs</literal> branch and they affect only those files directly |
|
421 under the <filename class='directory'>docs</filename> directory. However, |
|
422 the rules below have more counterintuitive consequences. |
|
423 </para> |
|
424 <programlisting>write user=docs/* branch=docs |
|
425 write user=docs/* file=docs/* |
|
426 read user=docs/* |
|
427 </programlisting> |
|
428 <para> |
|
429 These rules grant users whose keys are in the <filename |
|
430 class='directory'>docs</filename> subdirectory the power to change any file directly under the <filename class='directory'>docs</filename> directory, or any file at all in the <literal>docs</literal> branch. Indirectly, however, this adds up to the power to change any file on any branch, simply by making the change on the docs branch and then merging the change into another branch. |
|
431 </para> |
|
432 </listitem> |
|
433 </itemizedlist> |
|
434 </section> |
|
435 </section> |
|
436 <section> |
|
437 <title>How mercurial-server works</title> |
|
438 <para> |
|
439 All of the repositories controlled by mercurial-server are owned by a |
|
440 single user, the <systemitem |
|
441 class="username">hg</systemitem> user, which is why all URLs for |
|
442 mercurial-server repositories start with <uri>ssh://hg@...</uri>. |
|
443 Each SSH key that has access to the repository has an entry in |
|
444 <filename>~hg/.ssh/authorized_keys</filename>; this is how the SSH daemon |
|
445 knows to give that key access. When the user connects over SSH, their |
|
446 commands are run in a custom restricted shell; this shell knows which key |
|
447 was used to connect, determines what the user is trying to do, checks the |
|
448 access rules to decide whether to allow it, and if allowed invokes |
|
449 Mercurial internally, without forking. |
|
450 </para> |
|
451 <para> |
|
452 This restricted shell also ensures that certain Mercurial extensions are |
|
453 loaded when the user acts on a repository; these extensions check the |
|
454 access control rules for any changeset that the user tries to commit, and |
|
455 log all pushes and pulls into a per-repository access log. |
|
456 </para> |
|
457 <para> |
|
458 <command>refresh-auth</command> recurses through the <filename |
|
459 class='directory'>/etc/mercurial-server/keys</filename> and the <filename |
|
460 class='directory'>keys</filename> directory in the |
|
461 <filename |
|
462 class='directory'>hgadmin</filename> repository, creating an entry in |
|
463 <filename>~hg/.ssh/authorized_keys</filename> for each one. This is redone |
|
464 automatically whenever a change is pushed to <filename |
|
465 class='directory'>hgadmin</filename>. |
|
466 </para> |
|
467 </section> |
|
468 <section> |
|
469 <title>Security</title> |
|
470 <para> |
|
471 mercurial-server relies entirely on <command>sshd</command> to grant access to remote users. |
|
472 As a result, it runs no daemons, installs no setuid programs, and no part |
|
473 of it runs as <systemitem |
|
474 class="username">root</systemitem> except the install process: all programs run as the user |
|
475 <systemitem |
|
476 class="username">hg</systemitem>. Any attack on mercurial-server can only be started if the attacker |
|
477 already has a public key in <filename>~hg/.ssh/authorized_keys</filename>, |
|
478 otherwise <command>sshd</command> will bar the way. |
|
479 </para> |
|
480 <para> |
|
481 No matter what command the user tries to run on the remote system via SSH, |
|
482 mercurial-server is run. It parses the command line the user asked for, and |
|
483 interprets and runs the corresponding operation itself if access is |
|
484 allowed, so users can only read and add to history within repositories; |
|
485 they cannot run any other command. In addition, every push and pull is |
|
486 logged with a datestamp, changeset ID and the key that performed the |
|
487 operation. |
|
488 </para> |
|
489 <para> |
|
490 However, while the first paragraph holds no matter what bugs |
|
491 mercurial-server contains, the second depends on the relevant code being |
|
492 correct; though the entire codebase is short, mercurial-server is a fairly |
|
493 new program and may harbour bugs. Backups are essential! |
|
494 </para> |
|
495 </section> |
|
496 <section> |
|
497 <title>Legalese</title> |
|
498 <para> |
|
499 This program is free software; you can redistribute it and/or modify it |
|
500 under the terms of the GNU General Public License as published by the Free |
|
501 Software Foundation; either version 2 of the License, or (at your option) |
|
502 any later version. |
|
503 </para> |
|
504 <para> |
|
505 This program is distributed in the hope that it will be useful, but |
|
506 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
507 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
508 more details. |
|
509 </para> |
|
510 <para> |
|
511 You should have received a copy of the GNU General Public License along |
|
512 with this program; if not, write to the Free Software Foundation, Inc., 51 |
|
513 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
514 </para> |
|
515 </section> |
|
516 <section> |
|
517 <title>Thanks</title> |
|
518 <para> |
|
519 Thanks for reading this far. If you use mercurial-server, please tell me about |
|
520 it. |
|
521 </para> |
|
522 <para> |
|
523 Paul Crowley, <email>paul@lshift.net</email>, 2009 |
|
524 </para> |
|
525 </section> |
|
526 </article> |
|
527 |