--- a/README Tue Feb 24 10:31:48 2009 +0000
+++ b/README Fri Mar 06 08:56:48 2009 +0000
@@ -1,7 +1,8 @@
mercurial-server
-A set of tools for managing authorization and access control for
-ssh-based Mercurial repositories
+mercurial-server makes a group of repositories available to the developers
+you choose, identified by ssh keys, with easy key and access management
+based on hg.
Paul Crowley, paul@lshift.net, 2008-2009
@@ -10,74 +11,71 @@
http://hg.opensource.lshift.net/mercurial-server/
-WHAT IT GIVES YOU
-
-These tools make it easier to provide a centralized repository host
-with read/write access to many repositories for many developers.
-
-All of the repositories controlled by these tools are owned by a single user
-(the "hg" user in what follows), but many remote users can act on them, and
-different users can have different permissions. We don't use file permissions to
-achieve that - instead, developers log in as the "hg" user when they connect to
-the repository host using ssh, using ssh URLs of the form
-"ssh://hg@repository-host/repository-name". A restricted shell prevents them
-from using this access for unauthorized purposes. Developers are authenticated
-only using SSH keys; no other form of authentication is supported.
+All of the repositories controlled by mercurial-server are owned by a
+single user (the "hg" user in what follows), but many remote users can act
+on them, and different users can have different permissions. We don't use
+file permissions to achieve that - instead, developers log in as the "hg"
+user when they connect to the repository host using ssh, using ssh URLs of
+the form "ssh://hg@repository-host/repository-name". A restricted shell
+prevents them from using this access for unauthorized purposes. Developers
+are authenticated only using SSH keys; no other form of authentication is
+supported.
To give a user access to the repository, place their key in an
appropriately-named subdirectory of "/etc/mercurial-server/keys" and run
-"/etc/mercurial-server/refresh-auth". You can then control what access they have
-to what repositories by editing the control file
-"/etc/mercurial-server/access.conf", which can match the names of these keys
-against a glob pattern.
+"/etc/mercurial-server/refresh-auth". You can then control what access they
+have to what repositories by editing the control file
+"/etc/mercurial-server/access.conf", which can match the names of these
+keys against a glob pattern.
For convenient remote control of access, you can instead (if you have the
privileges) make changes to a special repository called "hgadmin", which
-contains its own "access.conf" file and "keys" directory. Changes pushed to this
-repository take effect immediately. The two "access.conf" files are
+contains its own "access.conf" file and "keys" directory. Changes pushed to
+this repository take effect immediately. The two "access.conf" files are
concatenated, and the keys directories merged.
QUICK START
-You and all developers using this system will need an SSH public key, and will
-almost certainly want to be running ssh-agent (or its equivalent, eg Pageant
-under Windows). If you're not familiar with ssh-agent, you should learn about
-that before using this.
+You and all developers using this system will need an SSH public key, and
+will almost certainly want to be running ssh-agent (or its equivalent, eg
+Pageant under Windows). If you're not familiar with ssh-agent, you should
+learn about that before using this.
-In what follows, certain operations (eg installing mercurial-server itself) have
-to be done on the repository server (which we call "repository-host"), but any
-operation that involves checking in or out of Mercurial can be done wherever is
-most convenient to you; the most usual arrangment would be that you'd do these
-things at the machine you sit at, and on which you run ssh-agent, which is what
-authenticates you when you talk to the repository server.
+In what follows, certain operations (eg installing mercurial-server itself)
+have to be done on the repository server (which we call "repository-host"),
+but any operation that involves checking in or out of Mercurial can be done
+wherever is most convenient to you; the most usual arrangment would be that
+you'd do these things at the machine you sit at, and on which you run
+ssh-agent, which is what authenticates you when you talk to the repository
+server.
-Ensure there is no user called "hg" on the repository host, and run "./install".
-This installs the mercurial-server files and control files, and creates and sets
-up the "hg" user.
+Ensure there is no user called "hg" on the repository host, and run
+"./install". This installs the mercurial-server files and control files, and
+creates and sets up the "hg" user.
-Place your SSH public key in the directory "/etc/mercurial-server/keys/root". I
-suggest creating yourself a directory and naming the key after your hostname (ie
-the file is called something like
-"/etc/mercurial-server/keys/root/yourname/yourhostname") so that you can easily
-manage users who have a different key on each host they use. Then run
+Place your SSH public key in the directory "/etc/mercurial-server/keys/root".
+I suggest creating yourself a directory and naming the key after your hostname
+(ie the file is called something like
+"/etc/mercurial-server/keys/root/yourname/yourhostname") so that you can
+easily manage users who have a different key on each host they use. Then run
"/etc/mercurial-server/refresh-auth".
-The repository is now ready to use, and you are now the sole user able to change
-and create repositories on this repository host.
+The repository is now ready to use, and you are now the sole user able to
+change and create repositories on this repository host.
CREATING REPOSITORIES
-To create a new repository, you clone a local repository onto the remote server.
-So if you want a new empty repository called "myproject", you can do (as
-yourself):
+To create a new repository, you clone a local repository onto the remote
+server. So if you want a new empty repository called "myproject", you can do
+(as yourself):
hg init myproject
hg clone myproject ssh://hg@repository-host/myproject
ADDING OTHER USERS
-Because your key is in the "keys/root" subdirectory, you have the equivalent of
-"root privileges" over mercurial-server (not the whole computer, just
+Because your key is in the "keys/root" subdirectory, you have the equivalent
+of "root privileges" over mercurial-server (not the whole computer, just
mercurial-server). You can add other root users by putting their keys next to
yours, or you can make less privileged users by putting their keys in the
"keys/users" subdirectory - these users will be able to read and write to any
@@ -110,17 +108,17 @@
In other words, hgadmin is a version controlled version of
"/etc/mercurial-server/keys", and changes to it take effect immediately. Only
"keys/root" users can act on "hgadmin" - those with keys in "keys/users" are
-locked out. Multiple admins can use Mercurial's version control to cooperate on
-controlling access to the repository server in a natural way. You can also add
-"root" users by putting their key in the "keys/root" directory in just the same
-way - these users will now be able to control hgadmin and create new
+locked out. Multiple admins can use Mercurial's version control to cooperate
+on controlling access to the repository server in a natural way. You can also
+add "root" users by putting their key in the "keys/root" directory in just the
+same way - these users will now be able to control hgadmin and create new
repositories just as you can.
-Once you're working with "hgadmin", it can be convenient to remove all the keys
-in "/etc/mercurial-server/keys" and all the entries in
+Once you're working with "hgadmin", it can be convenient to remove all the
+keys in "/etc/mercurial-server/keys" and all the entries in
"/etc/mercurial-server/access.conf" and use hgadmin to control everything. If
-you find yourself locked out, you can get back in again by restoring some of the
-entries you removed from these files - remember,
+you find yourself locked out, you can get back in again by restoring some of
+the entries you removed from these files - remember,
"/etc/mercurial-server/access.conf" takes precedence over the "access.conf" in
"hgadmin".
@@ -128,8 +126,9 @@
Out of the box, there are just two kinds of users: the ones with keys in
"keys/root" and those in "keys/users". However, you can change this by editing
-"access.conf". There are two "access.conf" files, one in "/etc/mercurial-server"
-and one in "hgadmin"; the two are simply concatenated before being read.
+"access.conf". There are two "access.conf" files, one in
+"/etc/mercurial-server" and one in "hgadmin"; the two are simply concatenated
+before being read.
Each line of access.conf has the following syntax:
@@ -176,13 +175,13 @@
When the first two of these decisions are being made, nothing is known about
what files might be changed, and so all file conditions automatically succeed
-for the purpose of such decisions. This means that doing tricky things with file
-conditions can have counterintuitive consequences:
+for the purpose of such decisions. This means that doing tricky things with
+file conditions can have counterintuitive consequences:
- You cannot limit read access to a subset of a repository with a "read" rule
-and a file condition: any user who has access to a repository can read all of it
-and its full history. Such a rule can only have the effect of masking a later
-"write" rule, as in this example:
+and a file condition: any user who has access to a repository can read all of
+it and its full history. Such a rule can only have the effect of masking a
+later "write" rule, as in this example:
read repo=specialrepo file=dontwritethis
write repo=specialrepo
@@ -192,11 +191,11 @@
- For similar reasons, don't give "init" rules file conditions.
-- Don't try to deny write access to a particular file on a particular branch - a
-developer can write to the file on another branch and then merge it in. Either
-deny all writes to the branch from that user, or allow them to write to all the
-files they can write to on any branch. In other words, something like this will
-have the intended effect:
+- Don't try to deny write access to a particular file on a particular branch -
+a developer can write to the file on another branch and then merge it in.
+Either deny all writes to the branch from that user, or allow them to write to
+all the files they can write to on any branch. In other words, something like
+this will have the intended effect:
write user=docs/* branch=docs file=docs/*
@@ -212,19 +211,20 @@
When a developer attempts to connect to a repository via ssh, the SSH daemon
searches for a match for that user's key in ~hg/.ssh/authorized_keys. If the
-developer is authorised to connect to the repository they will have an entry in
-this file. The entry includes a "command" prefix which specifies that the
+developer is authorised to connect to the repository they will have an entry
+in this file. The entry includes a "command" prefix which specifies that the
restricted shell should be used; this shell is passed an argument identifying
-the developer. The shell parses the command the developer is trying to execute,
-and consults a rules file to see if that developer is allowed to perform that
-action on that repository. The bulk of the work of the restricted shell is done
-by the Python program "hg-ssh", but the shell script "hg-ssh-wrapper" sets up
-some configuration so that you can change it to suit your local installation.
+the developer. The shell parses the command the developer is trying to
+execute, and consults a rules file to see if that developer is allowed to
+perform that action on that repository. The bulk of the work of the restricted
+shell is done by the Python program "hg-ssh", but the shell script
+"hg-ssh-wrapper" sets up some configuration so that you can change it to suit
+your local installation.
-The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", which recurses
-through two directories of files containing SSH keys and generates an entry in
-authorized_keys for each one, using the name of the key file as the identifier
-for the developer. These keys will live in the "keys" subdirectory
+The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", which
+recurses through two directories of files containing SSH keys and generates an
+entry in authorized_keys for each one, using the name of the key file as the
+identifier for the developer. These keys will live in the "keys" subdirectory
"/etc/mercurial-server" and the "keys" subdirectory of a repository called
"hgadmin". A hook in this repository re-runs "refresh-auth" on the most recent
version after every push.
@@ -236,18 +236,18 @@
SECURITY OF MERCURIAL-SERVER
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.
+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.
+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