114 not necessarily the repository server) and you want to give them user-level |
114 not necessarily the repository server) and you want to give them user-level |
115 access to the repository server. Run these commands: |
115 access to the repository server. Run these commands: |
116 |
116 |
117 hg clone ssh://hg@repository-server/hgadmin |
117 hg clone ssh://hg@repository-server/hgadmin |
118 cd hgadmin |
118 cd hgadmin |
119 mkdir keys/user/thatuser |
119 mkdir keys/users/thatuser |
120 cp /tmp/theirkey keys/user/thatuser/theirhostname |
120 cp /tmp/theirkey keys/users/thatuser/theirhostname |
121 hg add |
121 hg add |
122 hg commit -m "Added key for thatuser" |
122 hg commit -m "Added key for thatuser" |
123 hg push |
123 hg push |
124 |
124 |
125 In other words, hgadmin is a version controlled version of |
125 In other words, hgadmin is a version controlled version of |
126 "/etc/mercurial-server/keys", and changes to it take effect immediately. Only |
126 "/etc/mercurial-server", and changes to it take effect immediately - |
127 "keys/root" users can act on "hgadmin" - those with keys in "keys/users" are |
127 "refresh-auth" is run after every push. |
128 locked out. Multiple admins can use Mercurial's version control to cooperate |
|
129 on controlling access to the repository server in a natural way. You can also |
|
130 add "root" users by putting their key in the "keys/root" directory in just the |
|
131 same way - these users will now be able to control hgadmin and create new |
|
132 repositories just as you can. |
|
133 |
128 |
134 Once you're working with "hgadmin", it can be convenient to remove all the |
129 With the default access.conf file (see doc/configuring-access for more |
135 keys in "/etc/mercurial-server/keys" and all the entries in |
130 details) only users in "keys/root" can act on "hgadmin" - those with keys in |
|
131 "keys/users" cannot even read this repository. So multiple admins can use |
|
132 Mercurial's version control to cooperate on controlling access to the |
|
133 repository server in a natural way. |
|
134 |
|
135 You can also create an "access.conf" file in hgadmin, and this is appended to |
|
136 /etc/mercurial-server/access.conf whenever this is read - in other words, |
|
137 rules in the latter take precedence over those in the former. So once you're |
|
138 working with "hgadmin", it can be convenient to remove all the keys in |
|
139 "/etc/mercurial-server/keys" and all the entries in |
136 "/etc/mercurial-server/access.conf" and use hgadmin to control everything. If |
140 "/etc/mercurial-server/access.conf" and use hgadmin to control everything. If |
137 you find yourself locked out, you can get back in again by restoring some of |
141 you find yourself locked out, you can get back in again by restoring some of |
138 the entries you removed from these files - remember, |
142 the entries you removed from these files. |
139 "/etc/mercurial-server/access.conf" takes precedence over the "access.conf" in |
|
140 "hgadmin". |
|
141 |
143 |
142 ACCESS.CONF |
144 MORE INFORMATION |
143 |
145 |
144 Out of the box, there are just two kinds of users: the ones with keys in |
146 For more on how to use mercurial-server and configure access, see the files in |
145 "keys/root" and those in "keys/users". However, you can change this by editing |
147 the doc directory. |
146 "access.conf". There are two "access.conf" files, one in |
|
147 "/etc/mercurial-server" and one in "hgadmin"; the two are simply concatenated |
|
148 before being read. |
|
149 |
|
150 Each line of access.conf has the following syntax: |
|
151 |
|
152 <rule> <condition> <condition> ... |
|
153 |
|
154 Rule is one of |
|
155 |
|
156 init - allow any operation, including the creation of new repositories |
|
157 write - allow reads and writes to this file in this repository |
|
158 read - allow the repo to be read but reject matching writes |
|
159 deny - deny all requests |
|
160 |
|
161 A condition is a globpattern matched against a relative path, one of: |
|
162 |
|
163 user=<globpattern> - user's key |
|
164 repo=<globpattern> - repo (as the user supplies it) |
|
165 file=<globpattern> - file in the repo |
|
166 branch=<globpattern> - name of the branch |
|
167 |
|
168 The first rule in the file which has all its conditions satisfied is used to |
|
169 determine whether an action is allowed. |
|
170 |
|
171 Paths cannot contain any special characters except "/"; glob patterns cannot |
|
172 contain any special characters except "/" and "*". "*" matches zero or more |
|
173 characters not including "/" while "**" matches zero or more characters |
|
174 including "/". |
|
175 |
|
176 Blank lines and lines that start with "#" are ignored. |
|
177 |
|
178 FILE CONDITIONS |
|
179 |
|
180 mercurial-server supports file and branch conditions, which restrict an |
|
181 operation depending on what files it modifies and what branch the work is on. |
|
182 However, the way these conditions work is subtle and can be counterintuitive - |
|
183 if you want to keep things simple, stick to user and repo conditions, and then |
|
184 things are likely to work the way you would expect. |
|
185 |
|
186 The rules file is used to make four decisions: |
|
187 |
|
188 - Whether to allow a repository to be created |
|
189 - Whether to allow access to a repository |
|
190 - Whether to allow a changeset on a particular branch at all |
|
191 - Whether to allow a changeset to change a particular file |
|
192 |
|
193 When the first two of these decisions are being made, nothing is known about |
|
194 what files might be changed, and so all file conditions automatically succeed |
|
195 for the purpose of such decisions. This means that doing tricky things with |
|
196 file conditions can have counterintuitive consequences: |
|
197 |
|
198 - You cannot limit read access to a subset of a repository with a "read" rule |
|
199 and a file condition: any user who has access to a repository can read all of |
|
200 it and its full history. Such a rule can only have the effect of masking a |
|
201 later "write" rule, as in this example: |
|
202 |
|
203 read repo=specialrepo file=dontwritethis |
|
204 write repo=specialrepo |
|
205 |
|
206 allows all users to read specialrepo, and to write to all files *except* that |
|
207 any changeset which writes to "dontwritethis" will be rejected. |
|
208 |
|
209 - For similar reasons, don't give "init" rules file conditions. |
|
210 |
|
211 - Don't try to deny write access to a particular file on a particular branch - |
|
212 a developer can write to the file on another branch and then merge it in. |
|
213 Either deny all writes to the branch from that user, or allow them to write to |
|
214 all the files they can write to on any branch. In other words, something like |
|
215 this will have the intended effect: |
|
216 |
|
217 write user=docs/* branch=docs file=docs/* |
|
218 |
|
219 But something like this will not have the intended effect; it will effectively |
|
220 allow these users to write to any file on any branch, by writing it to "docs" |
|
221 first: |
|
222 |
|
223 write user=docs/* branch=docs |
|
224 write user=docs/* file=docs/* |
|
225 read user=docs/* |
|
226 |
|
227 HOW IT WORKS |
|
228 |
|
229 When a developer attempts to connect to a repository via ssh, the SSH daemon |
|
230 searches for a match for that user's key in ~hg/.ssh/authorized_keys. If the |
|
231 developer is authorised to connect to the repository they will have an entry |
|
232 in this file. The entry includes a "command" prefix which specifies that the |
|
233 restricted shell "/usr/local/lib/mercurial-server/hg-ssh" should be used; this |
|
234 shell is passed an argument identifying the developer. The shell parses the |
|
235 command the developer is trying to execute, and consults a rules file to see |
|
236 if that developer is allowed to perform that action on that repository. |
|
237 |
|
238 The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", which |
|
239 recurses through two directories of files containing SSH keys and generates an |
|
240 entry in authorized_keys for each one, using the name of the key file as the |
|
241 identifier for the developer. These keys will live in the "keys" subdirectory |
|
242 "/etc/mercurial-server" and the "keys" subdirectory of a repository called |
|
243 "hgadmin". A hook in this repository re-runs "refresh-auth" on the most recent |
|
244 version after every push. |
|
245 |
|
246 Finally, hook in an extension is run for each changeset that is remotely |
|
247 committed, which uses the rules file to determine whether to allow the |
|
248 changeset. |
|
249 |
|
250 SECURITY OF MERCURIAL-SERVER |
|
251 |
|
252 mercurial-server relies entirely on sshd to grant access to remote users. As a |
|
253 result, it runs no daemons, installs no setuid programs, and no part of it |
|
254 runs as root except the install process: all programs run as the user hg. And |
|
255 any attack on mercurial-server can only be started if the Bad Guys already |
|
256 have a public key in ~hg/.ssh/authorized_keys, otherwise sshd will bar the |
|
257 way. No matter what command the user tries to run on the remote system via |
|
258 ssh, mercurial-server is run. |
|
259 |
|
260 It parses the command line the user asked for, and interprets and runs the |
|
261 corresponding hg operation itself if access is allowed, so users can only read |
|
262 and add to history within repositories; they cannot run any other hg command. |
|
263 In addition, every push and pull is logged with a datestamp, changeset ID and |
|
264 the key that performed the operation. |
|
265 |
|
266 However, while the first paragraph holds no matter what bugs mercurial-server |
|
267 contains, the second depends on the relevant code being correct; though the |
|
268 entire codebase is currently only about twice as long as this README, |
|
269 mercurial-server is a fairly new program and may harbour bugs. Backups are |
|
270 essential! |
|
271 |
148 |
272 THANKS |
149 THANKS |
273 |
150 |
274 Thanks for reading this far. If you use mercurial-server, please tell me about |
151 Thanks for reading this far. If you use mercurial-server, please tell me about |
275 it. |
152 it. |