By David Renshaw and Kenton Varda - 05 May 2015
We sometimes describe Sandstorm as: “Like Google Docs, except open source, you can run it on your own server, and you can extend it with apps written by anyone.”
Sandstorm is all about collaboration – we have apps for real-time collaborative document editing, chat rooms, even collaborative music streaming. Collaboration, of course, requires access control. Sometimes you want some people to be able to edit a document while others can only read. Up until now, Sandstorm relied on each app to implement its own access control model, and many simply did not. For example, with Etherpad on Sandstorm before now, you could only share full write access.
Today, we’re introducing Sandstorm’s new built-in sharing model. With it, apps can define a set of “permissions” (like “read” and “write”) which make sense for the app, and then Sandstorm itself will present a user interface by which the user can grant these permissions to other users. Since Sandstorm is designed to support fine-grained app containers (where, for example, each Etherpad document runs as a completely separate instance of the app in its own container), Sandstorm can implement this access control model at the container level, freeing the app of most of the work. The app need not track users itself; Sandstorm will tell it (e.g. through HTTP headers) exactly which permissions the current user has, so all the app needs to do is implement those.
Moreover, Sandstorm implements a radical capability-based sharing model, which emphasizes the importance of delegation. Under our model, if you have access to a document, you can share that access with others, without requiring the document owner to intervene. This is important, because any obstacle to delegation is an obstacle to getting work done. Marc Stiegler said it best:
The truth of the matter is: delegation cannot be prevented. The further truth of the matter is: we do not appreciate how fortunate it is that delegation cannot be prevented. Because in fact, delegation is the cornerstone of civilization. - Marc Stiegler
More on this in a bit, but first let’s look at how it works.
Consider the GitWeb app. With the new sharing features in place, after Alice creates a new repository she can, for example, share read-only access with Bob and share read/write access with Carol.
Then, in turn, both Bob and Carol can reshare the repo to other users. If they both share their full access to Dave, then Dave gets read/write access.
If Alice now unshares with Carol, then Carol loses all access and Dave loses write access. Dave continues to hold the read-only access that he received from Bob. Carol’s share to Dave continues to exist, but it no longer carries any permissions, as Carol herself no longer holds any permissions.
Throughout this whole interaction, the app itself has no need to keep track of users! It only needs to know how to filter requests based on permissions. Teaching GitWeb to do this was easy, requiring only a few small changes in configuration files. The app remains dead simple. The only data that it stores is the Git repository that it hosts. There is no in-app user database.
Apps have complete control over the meanings of permissions. While “can read” and “can write” permissions will be sufficient in many cases, some apps, such as Groove Basin, might support a much wider range of permissions. In our updated Groove Basin package, sharing carries such diverse permissions as “can listen,” “can control the audio stream,” “can upload music,” and “can edit tags and delete music.”
Traditional access control is accomplished using “access control lists” (ACLs), in which a document owner (Alice) maintains an ACL for the document specifying exactly who has access (Bob and Carol). In many systems, Bob and Carol cannot directly add a new person (Dave) to this ACL – they must ask Alice to do it. Usually, this is treated as a security “feature”.
Preventing delegation is not a feature. It provides no security benefit, and it creates obstacles to legitimate work.
For example, say Alice has asked Carol to update the document to add some data that Carol has collected, with a deadline of 6PM. Around 4PM, Carol realizes she won’t have time, so she asks her assistant, Dave, to do the work. Unfortunately, Dave doesn’t have access, and Alice is unavailable because she’s in a meeting. Now what?
Here’s what inevitably happens: Carol copies the whole document into a new document, and then shares that with Dave. Later, when Dave is done, Carol copies the contents of the new document back into the original, overwriting it.
Or, worse, Carol just gives Dave her password.
What just happened? Carol bypassed the access control that prevented delegation to Dave! In fact, she did so trivially; no “hacking” required. It is obvious, in fact, that there is no technology which would prevent Carol from delegating access to Dave, except to cut off all communications between Carol and Dave, which would be silly. So, our security “feature” actually provided no security benefit.
With that said, what Carol did was annoying and error-prone. It took time, and the document could have been damaged, especially if someone else were editing at the same time and had their changes overwritten. It would have been much better if Dave could have simply had direct access to the document.
So, that’s what Sandstorm allows.
There is an objection to unrestricted delegation which has some merit: preventing delegation can help guard against accidental leaks. For example, I might share a sensitive document with a coworker for review, but I might not trust that my coworker really understands the sensitivity of the document. I trust my coworker not to violate my wishes, but my coworker might not understand that I don’t want them to reshare. I’d feel a lot more comfortable if I can simply prohibit resharing. Yes, they can always go out of their way to get around any barrier I put up, but hopefully it will be obvious to them that they shouldn’t.
This is a valid point, but solving it via the heavy-handed ACL model is overkill. As a user, what I really want is not a draconian security wall, but two things:
Sandstorm aims to provide both of these:
For enterprise users, we will further develop features that allow system administrators to set policies and audit access across an organization.
Many users may never need these features. That’s fine – the basic sharing interface works intuitively without requiring you to understand “sharing graphs” or “policies”. But for those who need it, especially in a business setting, these features will be invaluable.
Sharing is a new feature and we still have lots of work to do on it, but the initial version is already live. If you want to try sharing but have not yet set up your own server, you can use the demo. We’ve already enabled nontrivial permissions on GitWeb, Groove Basin, and Etherpad, and more app updates will be coming. Better yet, try writing an app that takes avantage of the new features. Enabling apps to easily support sharing is just one more way that Sandstorm makes open source web apps viable.