diff -r 40a287c95661 -r 16056a9015f3 doc/manual.docbook --- a/doc/manual.docbook Wed Oct 14 12:46:38 2009 +0100 +++ b/doc/manual.docbook Wed Oct 14 14:29:39 2009 +0100 @@ -1,16 +1,20 @@ -
+
Sharing Mercurial repositories with mercurial-server PaulCrowley - 2009Paul Crowley + 2009Paul Crowley, LShift Ltd
About mercurial-server +Home page: + + mercurial-server is software for Debian and Ubuntu systems which gives your -developers remote read/write access to Mercurial repositories using SSH public +developers remote read/write access to Mercurial repositories using SSH public key authentication; it provides convenient and fine-grained key management and access control. @@ -18,9 +22,9 @@ mercurial-server is the easiest and most secure way for several developers to have read/write access to a central repository, but that's not the only way for several people to work on the same project using Mercurial; you -should be familiar with the other ways of -handling multiple commiters before deciding to use this. +should be familiar with the other ways of +handling multiple commiters before deciding to use this. Though mercurial-server is currently targeted at Debian-based systems such @@ -52,10 +56,26 @@
Step by step -mercurial-server authenticates users not using passwords but using SSH public keys; everyone who wants access to a mercurial-server repository will need such a key, so you'll need to familiarize yourself with them before proceeding. In combination with ssh-agent (or equivalents such as the Windows program Pageant), this means that users will not need to type in a password to access the repository. +mercurial-server authenticates users not using passwords but using SSH public +keys; everyone who wants access to a mercurial-server repository +will need such a key, so you'll need to familiarize yourself with them +before proceeding. In combination with ssh-agent (or +equivalents such as the Windows program Pageant), +this means that users will not need to type in a password to access the +repository. +
+Creating a repository host -In what follows, we assume that you usually sit at a machine called my-workstation and you wish to install mercurial-server on repository-host. First, you'll need to create an SSH public key if you haven't already. You should consult your system documentation on how to do this, but it should look something like this. +In what follows, we assume that you usually sit at a machine called +my-workstation and you wish to +install mercurial-server on repository-host. First, you'll need to +create an SSH public key if you haven't already. You should consult your +system documentation on how to do this, but it should look something like +this. user@my-workstation:~$ ssh-keygen @@ -90,7 +110,7 @@ Setting up mercurial-server (0.6.1) ... user@repository-host:~$ -mercurial-server is now installed on the repository host. Next, we need to give you permission to see its repositories. +mercurial-server is now installed on the repository host. Next, we need to give you permission to access its repositories. user@repository-host:~$ ssh-add -L > my-key @@ -101,8 +121,13 @@ Connection to shell closed. user@my-workstation:~$ -You can now create repositories on the remote machine and have complete read-write access to all of them; you need never log on to repository-host again. +You can now create repositories on the remote machine and have complete +read-write access to all of them; you need never log on to repository-host again. +
+
+Creating repositories user@my-workstation:~$ cd my-mercurial-project user@my-workstation:~/my-mercurial-project$ hg clone . ssh://hg@repository-host/repository/name @@ -116,8 +141,19 @@ searching for changes no changes found user@my-workstation:~/my-mercurial-project$ +
+
+Adding other users -As things stand, no-one but you has any access to any repositories you create on this system. In order to give anyone else access, you'll need a copy of their SSH public key. Once you have that key, you could give them access by logging into repository-host, putting their keys in the right place under /etc/mercurial-server/keys, and re-running sudo -u hg /usr/share/mercurial-server/refresh-auth. However, there's a more convenient way. +As things stand, no-one but you has any access to any repositories you +create on this system. In order to give anyone else access, you'll need a +copy of their SSH public key; we'll assume you have that key in +~/other-users-key.pub. You could give them access by +logging into repository-host, +putting the key in the right place under /etc/mercurial-server/keys, and re-running +sudo -u hg /usr/share/mercurial-server/refresh-auth. +However, there's a more convenient way. user@my-workstation:~/my-mercurial-project$ cd .. @@ -141,7 +177,159 @@ remote: added 1 changesets with 1 changes to 1 files user@my-workstation:~/hgadmin$ -The new user can now read and write to your ssh://hg@repository-host/repository/name repository. +The new user can now read and write to your +ssh://hg@repository-host/repository/name repository. +Most other changes to access control can be made simply by making and +pushing changes to hgadmin, and you can use Mercurial to +cooperate with other root users in the normal way. + +
+
+Basic access control + +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 keys/root, while the other user you gave access to is a normal user since their key is under keys/users. Keys that are not in either of these directories will by default have no access to anything. + + +Root users can edit hgadmin, create new repositories and read and write to existing ones. Normal users cannot access hgadmin 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 . + +
+
+
+How mercurial-server works + +All of the repositories controlled by mercurial-server are owned by a +single user, the hg user, which is why all URLs for +mercurial-server repositories start with ssh://hg@.... +Each SSH key that has access to the repository has an entry in +~hg/.ssh/authorized_keys; this is how the SSH daemon +knows to give that key access. When the user connects over SSH, their +commands are run in a specially crafted restricted shell; this shell knows +which key was used to connect, determines what the user is trying to do, +and checks the access rules to decide whether to allow it. + + +This restricted shell also ensures that certain Mercurial extensions are +loaded when the user acts on a repository; these extensions check the +access control rules for any changeset that the user tries to commit, and +log all pushes and pulls into a per-repository access log. + + +refresh-auth recurses through the /etc/mercurial-server/keys and the keys directory in the +hgadmin repository, creating an entry in +~hg/.ssh/authorized_keys for each one. This is redone +automatically whenever a change is pushed to hgadmin. + +
+
+Access control + +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 widget repository, but no other. We first copy Pat's SSH public key into the keys/widget/pat directory in hgadmin. Now mercurial-server knows about Pat's key, but will give Pat no access to anything because the key is not under either keys/root or keys/users. To grant this key access, we must give mercurial-server a new access rule, so we create a file in hgadmin called access.conf, with the following contents: + + write repo=widget user=widget/** + + +Pat will have read and write access as soon as we add, commit, and push these files. + + +Each line of access.conf has the following syntax: + + +rule condition condition... + + +Blank lines and lines that start with # are ignored. Rule is one of + + + +init: allow reads, writes, and the creation of new repositories + + +write: allow reads and writes + + +read: allow only read operations + + +deny: deny all requests + + + +When considering a request, mercurial-server steps through all the rules in /etc/mercurial-server/access.conf and then all the rules in access.conf in hgadmin 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. + + +By default, /etc/mercurial-server/access.conf has the following rules: + + + init user=root/** + deny repo=hgadmin + write user=users/** + + +These rules ensure that root users can do any operation on any repository, that no other users can access the hgadmin repository, and that those with keys in keys/users can read or write to any repository but not create repositories. + + +A condition is a globpattern matched against a relative path. The two most +important conditions are + + + +user=globpattern: path to the user's key + + +repo=globpattern: path to the repository + + + +"*" only matches one directory level, where "**" matches as many as you +want. More precisely, "*" matches zero or more characters not including "/" +while "**" matches zero or more characters including "/". + +
+File conditions + +Here be dragons... + +
+
+
+Security + +mercurial-server relies entirely on sshd to grant access to remote users. +As a result, it runs no daemons, installs no setuid programs, and no part +of it runs as root except the install process: all programs run as the user +hg. And any attack on mercurial-server can only be started if the Bad Guys +already have a public key in ~hg/.ssh/authorized_keys, +otherwise sshd will bar the way. + + +No matter what command the user tries to run on the remote system via SSH, +mercurial-server is run. It parses the command line the user asked for, and +interprets and runs the corresponding hg operation itself if access is +allowed, so users can only read and add to history within repositories; +they cannot run any other hg command. In addition, every push and pull is +logged with a datestamp, changeset ID and the key that performed the +operation. + + +However, while the first paragraph holds no matter what bugs +mercurial-server contains, the second depends on the relevant code being +correct; though the entire codebase is short, mercurial-server is a fairly +new program and may harbour bugs. Backups are essential! + +
+
+Thanks + +Thanks for reading this far. If you use mercurial-server, please tell me about +it. + + +Paul Crowley, paul@lshift.net, 2009