157 - Whether to allow a repository to be created |
162 - Whether to allow a repository to be created |
158 - Whether to allow access to a repository |
163 - Whether to allow access to a repository |
159 - Whether to allow a changeset on a particular branch at all |
164 - Whether to allow a changeset on a particular branch at all |
160 - Whether to allow a changeset to change a particular file |
165 - Whether to allow a changeset to change a particular file |
161 |
166 |
162 When the first two of these decisions are being made, nothing is known |
167 When the first two of these decisions are being made, nothing is known about |
163 about what files might be changed, and so all file conditions |
168 what files might be changed, and so all file conditions automatically succeed |
164 automatically succeed for the purpose of such decisions. This means |
169 for the purpose of such decisions. This means that doing tricky things with file |
165 that doing tricky things with file conditions can have |
170 conditions can have counterintuitive consequences: |
166 counterintuitive consequences: |
171 |
167 |
172 - You cannot limit read access to a subset of a repository with a "read" rule |
168 - You cannot limit read access to a subset of a repository with a |
173 and a file condition: any user who has access to a repository can read all of it |
169 "read" rule and a file condition: any user who has access to a |
174 and its full history. Such a rule can only have the effect of masking a later |
170 repository can read all of it and its full history. Such a rule can |
175 "write" rule, as in this example: |
171 only have the effect of masking a later "write" rule, as in this |
|
172 example: |
|
173 |
176 |
174 read repo=specialrepo file=dontwritethis |
177 read repo=specialrepo file=dontwritethis |
175 write repo=specialrepo |
178 write repo=specialrepo |
176 |
179 |
177 allows all users to read specialrepo, and to write to all files |
180 allows all users to read specialrepo, and to write to all files *except* that |
178 *except* that any changeset which writes to "dontwritethis" will be |
181 any changeset which writes to "dontwritethis" will be rejected. |
179 rejected. |
|
180 |
182 |
181 - For similar reasons, don't give "init" rules file conditions. |
183 - For similar reasons, don't give "init" rules file conditions. |
182 |
184 |
183 - Don't try to deny write access to a particular file on a particular |
185 - Don't try to deny write access to a particular file on a particular branch - a |
184 branch - a developer can write to the file on another branch and then |
186 developer can write to the file on another branch and then merge it in. Either |
185 merge it in. Either deny all writes to the branch from that user, or |
187 deny all writes to the branch from that user, or allow them to write to all the |
186 allow them to write to all the files they can write to on any branch. |
188 files they can write to on any branch. In other words, something like this will |
187 In other words, something like this will have the intended effect |
189 have the intended effect: |
188 |
190 |
189 write user=docs/* branch=docs file=docs/* |
191 write user=docs/* branch=docs file=docs/* |
190 |
192 |
191 But something like this will not have the intended effect; it will |
193 But something like this will not have the intended effect; it will effectively |
192 effectively allow these users to write to any file on any branch, by |
194 allow these users to write to any file on any branch, by writing it to "docs" |
193 writing it to "docs" first: |
195 first: |
194 |
196 |
195 write user=docs/* branch=docs |
197 write user=docs/* branch=docs |
196 write user=docs/* file=docs/* |
198 write user=docs/* file=docs/* |
197 read user=docs/* |
199 read user=docs/* |
198 |
200 |
199 HOW IT WORKS |
201 HOW IT WORKS |
200 |
202 |
201 When a developer attempts to connect to a repository via ssh, the SSH |
203 When a developer attempts to connect to a repository via ssh, the SSH daemon |
202 daemon searches for a match for that user's key in |
204 searches for a match for that user's key in ~hg/.ssh/authorized_keys. If the |
203 ~hg/.ssh/authorized_keys. If the developer is authorised to connect |
205 developer is authorised to connect to the repository they will have an entry in |
204 to the repository they will have an entry in this file. The entry |
206 this file. The entry includes a "command" prefix which specifies that the |
205 includes a "command" prefix which specifies that the restricted shell |
207 restricted shell should be used; this shell is passed an argument identifying |
206 should be used; this shell is passed an argument identifying the |
208 the developer. The shell parses the command the developer is trying to execute, |
207 developer. The shell parses the command the developer is trying to |
209 and consults a rules file to see if that developer is allowed to perform that |
208 execute, and consults a rules file to see if that developer is allowed |
210 action on that repository. The bulk of the work of the restricted shell is done |
209 to perform that action on that repository. The bulk of the work of |
211 by the Python program "hg-ssh", but the shell script "hg-ssh-wrapper" sets up |
210 the restricted shell is done by the Python program "hg-ssh", but the |
212 some configuration so that you can change it to suit your local installation. |
211 shell script "hg-ssh-wrapper" sets up some configuration so that you |
213 |
212 can change it to suit your local installation. |
214 The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", which recurses |
213 |
215 through two directories of files containing SSH keys and generates an entry in |
214 The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", |
216 authorized_keys for each one, using the name of the key file as the identifier |
215 which recurses through a directory of files containing SSH keys and |
217 for the developer. These keys will live in the "keys" subdirectory |
216 generates an entry in authorized_keys for each one, using the name of |
218 "/etc/mercurial-server" and the "keys" subdirectory of a repository called |
217 the key file as the identifier for the developer. These keys will |
219 "hgadmin". A hook in this repository re-runs "refresh-auth" on the most recent |
218 live in the "keys" subdirectory of a repository called "hgadmin". A |
|
219 hook in this repository re-runs "refresh-auth" on the most recent |
|
220 version after every push. |
220 version after every push. |
221 |
221 |
222 Finally, a hook in an extension is run for each changeset that is |
222 Finally, hook in an extension is run for each changeset that is remotely |
223 remotely committed, which uses the rules file to determine whether to |
223 committed, which uses the rules file to determine whether to allow the |
224 allow the changeset. |
224 changeset. |
225 |
225 |
226 LOCKED OUT? |
226 LOCKED OUT? |
227 |
227 |
228 Once you're working with "hgadmin", it can be convenient to remove all the keys |
228 Once you're working with "hgadmin", it can be convenient to remove all the keys |
229 in "/etc/mercurial-server/keys" and all the entries in |
229 in "/etc/mercurial-server/keys" and all the entries in |