Demonstration release of the principles underpinning krsd.
[krsd] / README
1
2 krsd - A Kerberised RemoteStorage server implementation
3 =======================================================
4
5 Contents:
6
7 1. Introduction
8 2. Overview
9 2.1 remotestorage
10 2.2 webfinger
11 2.3 authorization tools
12 2.4 storage system
13 3. Installing
14 3.1 Dependencies
15 3.2 Getting the code
16 3.3 Building
17 3.4 Installing system-wide
18 3.5 Setting options
19 3.6 Integrating authorization
20
21 1) Introduction
22 ---------------
23
24 remotestorage is an open specification for personal data storage. It is supposed
25 to replace the currently popular proprietary "cloud storage" protocols using an
26 open standard and thereby promoting the seperation of applications and their
27 data on the web.
28
29 For more information, check out these links:
30   * http://remotestorage.io/ - Information about the remotestorage protocol
31                                and current implementations.
32   * http://unhosted.org/     - Philosophy, hands-on Tutorials and App collection.
33
34 2) Overview
35 -----------
36
37 krsd brings three things:
38 * a HTTP endpoint implementing remotestorage: /storage/{user}
39 * a HTTP endpoint implementing webfinger: /.well-known/webfinger
40
41 User management is based on Kerberos identities.  The SPNEGO mechanism
42 specified in RFC 4559 is used to this end.  Briefly put, this is a GSS-API
43 exchange embedded as base64 in WWW-Authenticate and Authorization headers
44 of the Negotiate type.
45
46 User accounts are unrelated to accounts on the server hosting this service.
47 Storage is both available to users and to services, and each is identified
48 with their usual principal names, including forms like these:
49
50         xmpp/xmpp.arpa2.net@ARPA2.NET
51         john@ARPA2.NET
52         john/admin@ARPA2.NET
53
54 These forms are translated to paths on the local filesystem as described
55 below, under "Storage system".
56
57 krsd is a fork of the useful work on rs-serve, and the respective
58 locations of the original and derived work are:
59 https://github.com/remotestorage/rs-serve
60 https://github.com/arpa2/krsd
61 The name has been changed to avoid confusion with application users.  It is
62 not clear to date if this project will live its own life or get integrated
63 with the original branch.  In the first case, a separate name brings
64 clarity; in the second, it has been harmless.
65
66 krsd is entirely written in C, using mostly POSIX library functions. It
67 relies on a few portable libraries, see the list under "Dependencies" below.
68 It does however currently use the signalfd() system call, which is only
69 available on Linux. (this is a solvable problem though, if you want to
70 be able to run on another system, please open an issue to ask for help)
71
72 2.1) remotestorage
73 ------------------
74
75 The currently implemented protocol version is "draft-dejong-remotestorage-01".  It has been modified to permit implied, that is HTTP-level, authentication and authorisation.  Demo code is available in a separate directory.
76
77 Currently the following features are supported:
78 * CORS support for all verbs (TODO: May not work at present)
79 * GET, PUT, DELETE requests on files and folders
80 * Opaque version strings (in directory listings and "ETag" header)
81 * Conditional GET, PUT and DELETE requests ("If-Match", "If-None-Match" headers)
82 * Protection of all non-public paths via authentication by the browser at the HTTP level, and authorisation based on a .k5remotestorage file in the destination file system
83 * Special handling of public paths (i.e. those starting with /public/), such that
84   requests on non-directory paths succeed without authorization.
85 * HEAD requests on files and folders with "Content-Length" header
86   (not part of remotestorage-01, only enabled when --experimental flag is given)
87
88 2.2) webfinger
89 --------------
90
91 The webfinger implementation only serves information about remotestorage
92 and is currently not extensible.
93 The hostname part of user addresses is expected to be the hostname set for
94 the rs-serve instance. This currently defaults to "local.dev" and can be
95 overridden with the --hostname option.
96 Virtual hosting (== hosting storage for multiple domains from a single
97 instance) is currently not supported.
98
99 The pathname returned ermits for the krsd to parse out two components of
100 the pathname to which it stores: /storage/domain.tld/user/ should be at
101 the beginning of the URI if it is to be accepted as a remoteStorage URI
102 on krsd.  Anything after this is taken as a path into the storage
103 structures used.
104
105 2.3) authorization
106 ------------------
107
108 This version of rs-serve cannot employ the original authorization backend
109 and frontend, because it removes the implicit bearer flow described by
110 OAuth2, for reasons of security.  Instead, it relies on the implicit and
111 time-constrained access provided by Kerberos.
112
113 It might have been possible to rely on a bearer token obtained from a
114 Kerberos-specific OAuth2 node, which would have made minimal or no changes
115 to rs-serve, but the downside of that would be that the intermediate form
116 of the bearer tokens provide access for all times, whereas Kerberos tickets
117 passed directly put a time constraint on the exchange.  (This point however,
118 is negotiable. It seems that OAuth2 permits it.  Encryption to resource
119 and information-rich handling in the IDP would be possible, in a site
120 managed and controlled by the user's side of things.  Let's talk?)
121
122 Another option might have been to package Kerberos tickets in bearer tokens,
123 but that would have introduced an extra intermediate party with no added
124 value but unpacking / repacking the token, so it was deemed less attractive.
125
126 The current implementation does not constraint access to particular users,
127 or groups of users.  It is very likely that such a facility will be added
128 in a future version, possibly based on central management infrastructure.
129
130 The --auth-uri option now causes a warning, but is not fatal.
131
132
133 2.4) Storage system
134 -------------------
135
136 The payload data of the remotestorage endpoint is stored on the local filesystem
137 within the respective user's target directory.  Determining this directory is
138 done by splitting the principal name at the @ sign and reshaping it according
139 to these steps:
140
141  0. Initially, the pathname of a realm is a fixed string that is shared by
142     all principals.
143
144     Example 0a.
145         A fallback default could be /var/lib/krs/
146
147     Example 0b.
148         When using OpenAFS as a backing store for this service, the starting
149         point /afs/ may be more useful.
150
151  1. Firstly, the realm is removed and translated into its related domain name,
152     which should be supported in the surrounding infrastructure.  In case of
153     generic hosting, the surrounding infrastructure could be the DNS, with
154     DNSSEC validated for sites that use it.  The result from this mapping is
155     the DNS domain name, represented as lowercase characters without a
156     trailing dot.
157
158     Example 1a.
159         ARPA2.NET is setup in the local infrastructure, and its domain name
160         is found to be arpa2.net -- which is used as a pathname component.
161
162     Example 1b.
163         ARPA2.NET is not setup in local infrastructure, and it is looked up
164         in DNS under the same domain name, arpa2.net -- and if that site
165         thought it sufficiently important to sign with DNSSEC, then this
166         will be validated.  What is looked up under the domain name is a
167         TXT record named _kerberos, holding what should match literally
168         with the realm name, case included.  In case of a mismatch, fail to
169         help the user.  Since the realm is being looked up, rather than a
170         DNS hostname, there will not be a trace up to parent domains.
171
172     What we now concatenate the DNS-name to the installation directory
173     as another subdirectory level.
174
175  2. Secondly, the local part (before the @ sign) is treated literally as a
176     path, with one or more levels.  Note that this means that a slash is
177     treated as a directory separator.  The last level is, once again, a
178     directory name.
179
180     Example 2a.
181         john@ARPA2.NET will append john/ to the path found so far.
182
183     Example 2b.
184         john/admin@ARPA2.NET will append john/admin/ to the path found
185         so far.
186
187     Example 2c.
188         http/chitchat.arpa2.net will append http/chitchat.arpa2.net/ to
189         the path found so far.
190
191   3. Thirdly, a fixed directory name such as remotestorage/ is appended to
192      the path name.  This is done to separate remote storage from local
193      storage and from other remote storage components, and to make all the
194      other directories unavailable.  This is of no use to local storage, but
195      it is immensely useful when dealing with storage on an OpenAFS share
196      that is also employed for other purposes.
197
198 The result is a concrete path into a filesystem.  A few complete examples may
199 be helpful at this point.
200
201 Example.  The user john@ARPA2.NET could be found in DNS zone arpa2.net, and
202 dependent on local settings his files could end up in mounted locations like:
203
204   /afs/arpa2.net/john/remotestorage/...
205   /var/lib/krs/arpa2.net/john/remotestorage/...
206
207 Example.  After changing user-ID to john/admin under the same realm, the
208 files accessible to John are found in places like:
209
210   /afs/arpa2.net/john/admin/remotestorage/...
211   /var/lib/krs/arpa2.net/john/admin/remotestorage/...
212
213 Example.  When a server is not acting on behalf of a user (through S4U with
214 Constrained Delegation) but on its own title, it depends on its principal
215 name.  For example, xmpp/xmpp.arpa2.net@ARPA2.NET could be found on:
216
217   /afs/arpa2.net/xmpp/xmpp.arpa2.net/remotestorage/...
218   /var/lib/krs/arpa2.net/xmpp/xmpp.arpa2.net/remotestorage/...
219
220 The filesystem path is configured in the webfinger profile, and may or may
221 not relate to the Kerberos Principal Name used to access the resource.
222 For full flexibility, the remotestorage directory should hold a file named
223 .k5remotestorage which must hold the Kerberos Principal Name on a line of
224 its own, if it is to have read/write access to anything underneath this
225 directory.
226
227 The reliance on filesystem paths implies a few noteworthy restrictions:
228
229 * The remotestorage endpoint cannot be used to store both a directory and a file
230   under the same path (ignoring the trailing slash). That means you cannot store
231   /foo/bar/baz and /foo/bar, but only one of them. This is a natural restriction
232   of traditional filesystems, that is currently well adhered to by all apps using
233   remotestorage (as far as I know).
234
235 * MIME types may not be exact for files that were added "out-of-band", that is
236   not added via the remotestorage protocol, but by copying to the remotestorage/
237   directory by other means. krsd stores MIME type and character encoding
238   under the "user.mime_type" and "user.charset" extended attributes, given these
239   are supported by the underlying filesystem. When these attributes aren't set,
240   a MIME type is guessed using libmagic, which may not always yield desirable
241   results. (for example an empty file, created using "touch" will be transmitted
242   via remotestorage with a Content-Type header of "inode/x-empty; charset=binary")
243   If even libmagic fails to make sense of a file, the Content-Type is set to
244   "application/octet-stream; charset=binary".
245
246 * Filesystem privileges must be setup to grant access to the user.  In the
247   case of OpenAFS, this will be based on the user, and krsd will act
248   on behalf of the user when storing files.  In this case, Constrained
249   Delegation must be permissive to S4U2Proxy use, and the principal ticket
250   for the user must probably be created proxiable.  The details of this have
251   not been ironed out yet.
252
253 3) Installing
254 -------------
255
256 These steps should enable you to install krsd.
257
258 3.1) Dependencies
259 -----------------
260
261 - GNU make
262 - pkg-config (or tweak the Makefile)
263 - gcc
264 - libc
265 - libevent (>= 2.0)
266 - libmagic
267 - libattr
268 - BerkeleyDB
269
270 On Debian based systems, this should give you all you need:
271
272   apt-get install build-essential libevent-dev libmagic-dev libattr1-dev libssl-dev libdb-dev pkg-config
273
274 If you want to develop, you may also want debug symbols and valgrind (required by
275 leakcheck.sh script):
276
277   apt-get install libevent-dbg valgrind
278
279 3.2) Getting the code
280 ---------------------
281
282 Given you are reading this file, you probably have the code already, but just to
283 be sure:
284
285 Currently the krsd code is hosted on github.
286
287 You can browse it online, at:
288
289   https://github.com/arpa2/krsd
290
291 or close it using git:
292
293   git clone git://github.com/arpa2/krsd.git
294
295 Note that krsd itself is a clone of rs-serve, with the distinctive
296 feature that krsd introduces Kerberos authentication.
297
298 3.3) Building
299 -------------
300
301 Given you have all dependencies installed, simply run
302
303   make
304
305 and you should be good to go.
306
307 3.4) Installing system-wide
308 ---------------------------
309
310 To install the krsd binary to /usr/bin, run
311
312   make install
313
314 as a privileged user.
315
316 To install somewhere else, tweak the Makefile first.
317
318 This will also install an init script to /etc/init.d/krsd and a default
319 configuration to /etc/default/krsd.
320
321 On Debian based systems (i.e. when "update-rc.d" is present), "make install"
322 will also install the krsd init script into /etc/rc*.d/.
323
324 3.5) Setting options
325 --------------------
326
327 There are a variety of options 
328
329 If you want to use the init script, you can set options in /etc/default/krsd,
330 otherwise just pass them on the command line.
331
332 Run:
333
334   krsd --help
335
336 to get a list of supported options.
337
338 3.6) Integrating authorization
339 ------------------------------
340
341 To integrate an authorization endpoint, you need to do two things:
342
343 * configure endpoint URI
344
345   Set the --auth-uri option to a printf style format string. "%s" will be
346   replaced with the username.
347
348 * configure your authorization endpoint to manage krsd tokens
349
350   krsd doesn't care where tokens come from, but it need to know them to
351   decide whether a given request is authorized or not. It maintains an internal
352   store for authorizations (i.e. structures of [user-name, token, scopes]),
353   which must be managed from the outside.
354
355   The tools to do this are:
356
357   * rs-add-token:
358
359       Usage: rs-add-token <user> <token> <scope1> [<scope2> ... <scopeN>]
360
361     - <user> is the login name of the user (krsd must be able to resolve
362       it using getpwnam() in order to find the home directory)
363     - <token> is the token string authenticating future requests. For krsd
364       it is an opaque string.
365     - <scope1>..<scopeN> are scope strings in the same form as described in
366       draft-dejong-remotestorage-01, Section 9.
367
368   * rs-remove-token:
369
370       Usage: rs-remove-token <user> <token>
371
372     <user> and <token> must both be given.
373     If the token cannot be found, rs-remove-token terminates with non-zero status.
374
375   * rs-list-tokens:
376
377     Lists all currently installed tokens and their respective scopes.
378
379     The output format is primarily meant for (human) debugging and subject to change.
380
381 4) Contributing
382 ---------------
383
384 * Note that krsd is a fork of the original admirable work named rs-serve.
385   Never blame the rs-serve authors for mistakes that I (Rick) have added.
386   And don't expect them to support my mistakes!
387
388 * If you've found a bug, or have any questions, please open an issue on github:
389   https://github.com/remotestoage/rs-serve/issues
390
391 * If you want to contribute, fork the project on github and send pull requests.
392
393 * In any case, don't hesitate to talk with us on IRC:
394   #remotestorage and #unhosted, both on irc.freenode.org
395
396   Webchat links:
397   - #unhosted: http://webchat.freenode.net/?channels=unhosted
398   - #remotestorage: http://webchat.freenode.net/?channels=remotestorage
399