sandstorm-io / sandstorm

Sandstorm is a self-hostable web productivity suite. It's implemented as a security-hardened web app package manager.
https://sandstorm.io
Other
6.75k stars 706 forks source link

Accessing grain URL from within the grain #2820

Open eemeli opened 7 years ago

eemeli commented 7 years ago

Is there a way for a grain to gain knowledge of its grain id and/or grain URL?

I'm working on an application that fetches the user's email addresses with a powerbox request & using the EmailVerifier, and now I'd like to send the user an email that includes a link back to the grain, including a setPath'd location within the grain. I can get the hostname via HackSessionContext.getPublicId(), but how can I get the grain id or even the full grain URL? Or is there a different URL I could use that'd redirect appropriately?

kentonv commented 7 years ago

Currently there's no API for this. This is sortof-intentional, or at least it was back in the day when knowing the grain ID meant you could get access to the grain. Basically, we don't want an app to be able to bootstrap a low-bandwidth covert channel into a high-bandwidth one: if a grain can leak a small number of bits to an external party, then it could leak its own grain ID, and if that meant the external party could then access the grain directly, now they have a high-bandwidth connection. (Note that today this may sound silly because apps can freely make HTTP requests and send e-mail to anyone, but eventually we intend to implement full confinement, so apps won't be able to talk to the outside world without explicit permission.)

However, we log ago changed things so that the grain ID alone is not sufficient to get access to the grain -- you need a sharing link. We still want to make sure that an app cannot generate a sharing link to itself, but I'm not sure if there's any need to guard the grain ID. Certainly in the context of e-mail notifications, it would be nice to be able to link back to the app. So maybe we should add a way.

That said, there's another line of reasoning which says that what we really want here is for the app to be able to specify an e-mail template, and then instruct Sandstorm to substitute in certain values before sending. So then you'd stick {{grainUrl}} -- or even {{sharingLink role=edit}} -- into your outgoing message and Sandstorm would substitute as appropriate. This might actually be easier for developers, and avoids actually giving any IDs/tokens to the app.

Yet another line of reasoning says: Most apps send e-mail for notification purposes. In Sandstorm, they should really be using the notifications API, and let Sandstorm send an e-mail or not send an e-mail according to the user's preferences. Sandstorm would naturally add a link back to the grain in any such e-mail. (Currently, notifications are implemented but they do not yet generate e-mails; they only show up in the "bell menu" and as desktop notifications.)

Does your app's use of e-mail fall under "notifications"?

eemeli commented 7 years ago

Yes, it's effectively e-mail notifications that we're doing, and we're doing it from the grain because the Sandstorm e-mail notifications API isn't yet available. If/once it is, that would provide a much nicer way of handling these, especially as it allows dropping the requirement for the grain to request and get the user's email address, which is at least currently a somewhat convoluted process (for clearly good reasons, mind).

I do rather like the e-mail template approach, as that would simplify the amount of data that needs to pass back and forth. I don't think notifications are the only emails that apps/grains want to generate, and without a grain id it's somewhat difficult to uniquely identify (in a user-friendly manner, in particular) which of an app's grains on a specific host sent the message.

However, as I'm somewhat pressed for time and need a solution that gets me at least the grain id, what would you suggest as the least intrusive place for me to add that capability to our local Sandstorm instance? As in, if this functionality existed, where would it exist? Maybe as an additional field in the results of HackSessionContext.getPublicId()?

kentonv commented 7 years ago

An ugly but simple hack that doesn't require changing Sandstorm: Ask the grain creator to copy/paste the grain URL into the app as part of configuring it. Only needs to happen once per grain.

Otherwise, sure, either adding it to getPublicId() or adding a new method getGrainId() seem like reasonable choices.