rocicorp / repc

The canonical Replicache client, implemented in Rust.
Other
31 stars 7 forks source link

RFC: Lightweight Self-Signup #269

Closed phritz closed 3 years ago

phritz commented 3 years ago

Proposal below: https://github.com/rocicorp/repc/issues/269#issuecomment-731446716

phritz commented 3 years ago

issue on the diff-server side: https://github.com/rocicorp/diff-server/issues/64

phritz commented 3 years ago

Background

Problem

Since we don't yet have an accounts service the way a customer "signs up" for replicache is manually. They contact us and we create a PR adding a new id and client view url to the accounts list in the diffserver. This is less than ideal because:

So the problem to solve is this: enable a customer to be able to start using the diffserver without involving a human and with the fewest number of and easiest steps possible. We need to do this in a secure-enough way wrt the threat model below.

Non-goals

Threat model

There is additional info in the auth link above but the threat model for now is:

Out of scope, at least for now:

Proposal: Open auto-signup with guardrails

Let's err on the side of permissiveness for now but have some backstops, or easy potential backstops, in case of problems. Our strategy for now is to be able to easily mitigate problems if they happen, as opposed to preventing them from happening up front. Also, let's not call into existence new dependencies or infrastructure for the moment. And importantly, lets enable new customers to make different security tradeoffs in the name of convenience than established customers in production.

Let's allocate a range of Auto-Signup account IDs (aka "asid"s), say ids >= 1,000,000. We keep track of the next available auto-signup id in noms on the diffserver. There's a URL served by the diffserver say /auto-signup that when requested returns the next available asid and maybe some short instructions, and increments the next available id now that this asid is used. It should probably mention something about limitations, eg "This account can be used to get up and running with or to evaluate Replicache. Before deploying replicache to end users in production for non-evaluation purposes you will want to contact us at xxx so we can upgrade the account for production use. Otherwise, it will be subjected to certain restrictions eg a limit on the number of clients." We should try to get an optional email address with auto signup so we can contact them if we notice them exceeding reasonable limits or having other kinds of problems.

Asids are necessarily less trustworthy than regular account ids that we add manually to accounts.go. They are allocated in a separate range so we can if need be easily apply different policies to them than to regular accounts. Externally, to customers, they are just accounts -- we probably don't make a distinction, we just say that don't go into production for real without contacting us. When they do want to go into production for real we manually add a regular account for them to accounts.go and say "start sending this new id instead of the other one". We can set their clientview urls up for them in the new account so everything works just like before, except they are sending a new account id. There is no loss or reset of client data required.

Limits on accounts

Like today, there are no limits on what regular accounts can do. We require that they whitelist their client view url primarily so as to eliminate the risk of leaking user auth to random urls, and also to not create an open proxy. (We should let them specify multiple urls, btw.)

We can start with only some gross limits on asids:

I think that's probably all we start with. Should we need to, we can easily turn off asid diffserver access on an individual or complete basis by just checking account id sent in the pullrequest, without affecting regular users. We have a bunch of additional policies that we could implement should the need arise. These policies could just be alerts to us via logging an ERROR or could actually be enforced:

Bummers

Rough TODOs

Alternatives

aboodman commented 3 years ago

Thank you for putting this proposal together. I very much like the developer experience and scale of effort. Both make sense for where we are right now.

Comments:

implement /auto-signup which keeps a nextid in noms

If we store in Noms, then we need a special Noms db just to store this one integer. Because currently each account in diff-server has its own Noms database. This does not seem better than just storing this int directly in dynamodb.

if we lose the noms db that stores asids, everyone using one is SOL. This is a departure from present in that we can safely lose noms and restart fresh with no loss of data for customers (of course, there is the downtime).

We could turn on backups of the relevant s3 bucket. However that would also backup all the random diff server data that we don't want to backup.

Again, maybe better to put this in dynamodb. Then we can backup just the accounts.

we don't really have a way to get them to agree to an EULA, if that's important

Don't care about this, but it would be nice to get their name, email, and website. If we want to store this in Noms, we'd have to create a special "meta" dataset within each account db. I guess that's nbd, but this seems like another reason to just use dynamodb.

implement /auto-signup which keeps a nextid in noms

Nit: Can we call it just "signup". People don't need to know it's temporary or weird.

have a way to signal account errors back to the client, probably one that isn't great but works now, more grist for the #119 mill

Errors from /auto-signup? I'm imaging this is an HTML form. Were you imagining something you call programmatically?

phritz commented 3 years ago

implement /auto-signup which keeps a nextid in noms If we store in Noms, then we need a special Noms db just to store this one integer. Because currently each account in diff-server has its own Noms database. This does not seem better than just storing this int directly in dynamodb.

The advantage I was seeing is that is that the diffserver already directly uses noms, but does not directly use dynamo (the dependency is not visible to diffserver application code). So if we store it in noms we would introduce no new concepts into the diffserver, which has an appealing uniformity and simplicity to me.

if we lose the noms db that stores asids, everyone using one is SOL. This is a departure from present in that we can safely lose noms and restart fresh with no loss of data for customers (of course, there is the downtime). We could turn on backups of the relevant s3 bucket. However that would also backup all the random diff server data that we don't want to backup. Again, maybe better to put this in dynamodb. Then we can backup just the accounts.

Yeah that makes sense. If we can't specify a noms db for account info in a way that backs up only the relevant dynamo and s3 data w/o also backing up replicache client datasets, then yeah, seems better to put it into dynamo.

Nit: Can we call it just "signup"

Yes, from the user's perspective there should be no distinction, it should just be "signup" for an "account".

have a way to signal account errors back to the client, probably one that isn't great but works now, more grist for the #119 mill Errors from /auto-signup? I'm imaging this is an HTML form. Were you imagining something you call programmatically?

I meant signaling account errors from the diffserver back to the client. Like if we turn them off for some reason eg, they sign up 10,000 clients and don't respond to email, we want to signal that their replicache account is disabled and to contact us. We want to do this differently than 400 or 401. For now we're probably stuck with choosing a specific status code, dunno maybe 402, and having code that logs an ERROR when received.

aboodman commented 3 years ago

On Wed, Dec 2, 2020 at 8:16 AM Phritz notifications@github.com wrote:

implement /auto-signup which keeps a nextid in noms If we store in Noms, then we need a special Noms db just to store this one integer. Because currently each account in diff-server has its own Noms database. This does not seem better than just storing this int directly in dynamodb.

The advantage I was seeing is that is that the diffserver already directly uses noms, but does not directly use dynamo (the dependency is not visible to diffserver application code). So if we store it in noms we would introduce no new concepts into the diffserver, which has an appealing uniformity and simplicity to me.

Understood. That's appealing to me. It's kind of funny to prefer an unproven db that is used in only a handful of places to dynamodb, but hey ... it's our db.

if we lose the noms db that stores asids, everyone using one is SOL. This is a departure from present in that we can safely lose noms and restart fresh with no loss of data for customers (of course, there is the downtime). We could turn on backups of the relevant s3 bucket. However that would also backup all the random diff server data that we don't want to backup. Again, maybe better to put this in dynamodb. Then we can backup just the accounts.

Yeah that makes sense. If we can't specify a noms db for account info in a way that backs up only the relevant dynamo and s3 data w/o also backing up replicache client datasets, then yeah, seems better to put it into dynamo.

Wait a second, back up I don't think this chain of logic makes sense.

In your original proposal the only thing we're storing is a single "next_asid" int, right?

That has to be in a separate noms db, because the only noms dbs we currently have in diff server are per-account. So (a) we can back that up, but (b) do we even care? If we lose it it seems like what happens is maybe we have to figure out what the last one we gave out is or something. Not fatal.

If we want to store extra bits of information, like email address, then obviously putting them in the per-account noms dbs would make sense, but that would mean backing those up which we don't want to do.

So if we want to use Noms what we can do is create a new "accounts" noms db and store the global next_asid counter there and also per-account metadata we collect.

I can't decide the tradeoff between using Noms vs just using dynamodb directly. It's fun to use Noms. I feel like you're going to start complaining about the Noms marshalling API which is admittedly got some sharp edges. On the other hand dyanmodb API is also kind of grotty.

I'll let you make this call.

Nit: Can we call it just "signup"

Yes, from the user's perspective there should be no distinction, it should just be "signup" for an "account".

have a way to signal account errors back to the client, probably one that isn't great but works now, more grist for the #119 https://github.com/rocicorp/repc/issues/119 mill Errors from /auto-signup? I'm imaging this is an HTML form. Were you imagining something you call programmatically?

I meant signaling account errors from the diffserver back to the client. Like if we turn them off for some reason eg, they sign up 10,000 clients and don't respond to email, we want to signal that their replicache account is disabled and to contact us. We want to do this differently than 400 or

  1. For now we're probably stuck with choosing a specific status code, dunno maybe 402, and having code that logs an ERROR when received.

Ah, SG.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rocicorp/repc/issues/269#issuecomment-737406387, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAATUBCJBRBKBFJWO3GQDOTSS2AA5ANCNFSM4TVDGDUQ .

phritz commented 3 years ago

So if we want to use Noms what we can do is create a new "accounts" noms db and store the global next_asid counter there and also per-account metadata we collect.

Yes, this is what I had in mind if we use noms. Same page.

So (a) we can back that up, but (b) do we even care?

If we lose it easy enough to recover the next asid from the logs but we do lose all information about who has which account. But maybe we don't care for now.

I can't decide the tradeoff between using Noms vs just using dynamodb directly. It's fun to use Noms. I feel like you're going to start complaining about the Noms marshalling API which is admittedly got some sharp edges. On the other hand dyanmodb API is also kind of grotty.

I'm leaning towards the grotty I know vs the grotty I'd have to learn. Will follow up in slack.

phritz commented 3 years ago

Taking a look at this work relative after holiday break, looking to cut scope so proposing that we break remaining work down into DO / DO NOT. @aboodman

Propose we DO:

Propose we DO NOT:

phritz commented 3 years ago

OK here's what's left. Items in each step can be done in pretty much any order. Two main changes that need to roll out are 1) updating documentation to refer to our new signup page and 2) sending clientViewURL in the PullRequest (JS -> repc -> diffs).

Step 1: finish up

Step 2: release

Step 3: follow-up


Things we are NOT doing:

phritz commented 3 years ago

No longer relevant w/o the diffserver.

aboodman commented 3 years ago

🍺 Pouring one out.

On Mon, Mar 8, 2021 at 8:58 AM Phritz notifications@github.com wrote:

No longer relevant w/o the diffserver.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rocicorp/repc/issues/269#issuecomment-792992874, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAATUBHJ3P7HGIG5CDFXQMDTCUM3LANCNFSM4TVDGDUQ .