One you implement validation functions [1] on user databases to control what kind of data can be inserted into couch. These functions can only be changed by database admins, not users, so can act as a security mechanism controlling what goes in.
As mentioned by others you can also implement a proxy. This doesn't have to interfere with sync functionality, you just have to make sure you proxy all the endpoints in the replication protocol [2]. Envoy [3] is one such proxy that essentially applies document level permissions to a CouchDB database without interfering with sync.
If the goal is just to limit document size, or throttle clients trying to hammer the API, this doesn't even have to be a custom proxy, and reverse proxy with the needed control knobs (such as NGINX) will do. You can of course combine this with validation functions, using validations to ensure the everything that comes in is the right "shape" and using NGINX and it's ilk to apply throttling and sane request limits.
At scale there's a decent chance you want a proxy in front of your Couch instance anyway, since Couch is truly multi-master, meaning you probably want to balance your clients across all your nodes anyway.
[1] https://docs.couchdb.org/en/stable/ddocs/ddocs.html#validate... [2] https://docs.couchdb.org/en/stable/replication/protocol.html... [3] https://github.com/cloudant-labs/envoy
I'm not sure about current time but previously it was a problem that couchdb file grow until some limit on filesystem and couchdb just crashed.
Start of the envoy readme: it's not battle tested or supported in any way. Also it doesn't do any validation apart from limiting permissions for different users.
It's easier to reimplement couchdb than to create smart proxy that will estimate is this query expensive or not.
I'm not saying about rate-limiting proxy or load-balancing to different backends which could be implemented on nginx or something else.
1) The client you wrote is bugged and generated bad data. This scenarios can occur just as easily using Postgres and an application server. What does your app server do if a client tries to send bad data? (Answer: Whatever you told it to do. Most likely throwing a 500 when your databases refuses the incoming data.)
As for what will happen when pouch syncs to couch the server will let everything else sync, but not the bad document. The return value from the API call will tell you what documents didn't sync.
2) Someone is intentionally trying to shove bad data into your database. In this case it's worked as advertised and rejected the bad data. What do you care if a malicious client breaks?
What kind of "expensive" query are you envisioning? Mango queries don't support joins, and only simple equality filters, so in general the worst thing someone could do is send a query that doesn't use an index, but why are you letting the client query the server in the first place? Just have the client sync and query client side. Or don't allow access the the _find endpoint and restrict them to the map/reduce view you handwrote.
If you must let them send arbitrary queries (which to me implies a relatively trusted user, but let's pretend their not), then run the query with a limit of 1 or 0, and examine the execution stats to see if they are using an index, and check their query to see if their limit is reasonable. But at this point you've now entered into a scenario that's going to be very difficult with a custom API too.
I’ve limited document size to 10mb and ratelimited updates to 10 per second. Client starts to update document with random data 10 requests per second. As far as I understand couch stores all versions at least some time. This means that this one client could fill space on my server 100mb/s. There is no such issues with postgress, and no one allow clients execute raw queries on database without any application server. Document only 10mb but database is huge.
> What kind of "expensive" query are you envisioning?
I have never used couch, so I don’t know what could be expensive. May be some lookup without index or something like this.
Sorry for my ignorance, is it true that if I limit couch only to replication it will not be any not indexed lookups?
Looks like implement secure system with couch is very hard but I can’t find any best practices, mostly only authentication and basic validation.
Ah! Now we are getting somewhere! Your concerned about someone filling your disk.
OK, let's modify your scenario a little. Instead of updating an existing document, they create a new document. This a malicious client, why do updates that'll get cleaned up in a few minutes when I can make it permanent?
So, CouchDB allows these writes, and now your disk is full.
What does Postgres with a custom API do? Allows these writes, and now your disk is full.
Your allowing 10MB documents because that makes sense for your application right? So your Postgres table is going to have a binary column or some other column meant to hold bulk data, and your API is going to accept it.
If it doesn't make sense, lower the max document size. Apply validations to limit what fields can be written to, and how big they can be. In Postgres this is called your "schema". Couch being "schemaless", it's now your validation function. Couch is no different from any other schemaless database such as Mongo, RethinkDB and FoundationDB in this regard.
Also your rate limiting here is weak. If I can post to your sever at 100Mb/s second, I can saturate a 1GB link with only 10 clients. Doesn't matter if you reject my posts, if I can send them to the server, I can DOS you pretty easily.
The main thing Postgres gives you here is that it requires you to define your schema upfront (unless you use JSON columns, in which case it joins the schemaless club above). Couch will happily let you not, in which case someone wants to write a record of their car maintenance into your recipe book app? Couch is good with that. But take a step back. what actually stops them from putting that in the "description" column of your Postgres recipe app? Not much. So you have to think about what's important. Do I actually need to make sure these are all the same "shape"? If so I need a validation function. If I can just shrug and say "garbage in, garbage out", then I just need controls around how much data they can insert, but hey, I needed that for Postgres anyway.
> Sorry for my ignorance, is it true that if I limit couch only to replication it will not be any not indexed lookups?
Correct (enough). The entirety of CouchDB is built around efficient replication. While it's not going to use a formal "index" getting all of the changes after a specific rev is an efficient operation.
My idea that it’s very hard to create safe couchdb based system and most recommendations limited to setup nginx proxy and authenticate users which is not enough.
It is? It's unclear to me why I'm allowing 10 updates to a (largish, 10MB! Use a file or store it in S3!) document per-minute, but not 10 creates. Maybe I'm building Google Docs? Except I'd want old revisions, so those are creates. Plus 10 Mb is a huge spreadsheet. But sure lets roll with it. Actually Couch does not keep old versions of documents around, only old revision numbers. When a document is updated, the old version becomes eligible for compaction (basically garbage collection). So your attacker has to be fast enough to outrun the compactor, while being slow enough to not get temporarily banned from your service. It seems like less effort to me to use this power to flood your network I/O, which is almost certainly lower than your disk I/O. Or just choke your Postgres server on it's 100Mb/s disk I/O for updates + whatever is required to maintain your indexes.
I'm not actually advocating for Couch over Postgres. In my mind Postgres should be the default choice, and you switch to something else if you have a reason. For Couch, the biggest reason is sync is built in, in such a way that you can leverage it for your own applications with minimal effort. In my experience sync can be devilishly hard for non-trivial cases, so depending on your app, that can be pretty compelling.
But so far you seem to be focused on DOS attacks your not going to find separate advice for Postgres vs Mongo vs Couch, because the backing system doesn't matter. The attacks and mitigations are identical no matter the back-end, namely stop the traffic before it consumes your resources.
In case of couch I've not seen any secure open-source example.
I'm not focused on DOS attacks, I'm just proposing different attack vectors.
Spam prevention is not trivial but mostly solved problem. You can find a lot of articles about this topic.
But creating secure couchdb looks like very non-trivial.
Couch is no different. You have to understand Couch, you have to understand it's features and limitations, and build your system within those constraints.
You seem to be asserting because Couch is designed to be internet connected it can't be secure. If that's true, then I guess every customer on IBM Cloudant (Couch as a service), Realm (another database designed for mobile sync), and Firebase (Google database as a service) are all in trouble and just don't know it yet.
Security for all systems is non trivial. Thinking it is assures your system is not secure.
You can check even trivial rails blog or todo example from some book and it will be limited in scope but more or less secure. I'm having hard time to find secure couchdb example.
> Security for all systems is non trivial. But not equally hard.
If you use firebase you should understand that you getting vendor lock-in and in some cases you can spend much more money, but for some types of projects this platform is ok for me.
Same with couchdb, I understand that if I get replication with client, I need to pay by reorganising data or may be spend more resources to make system secure. There is no free lunch.
With the example o gave you could have a constraint in CouchDB achieve the effect but there are simply other examples one could use.
[1] https://stackoverflow.com/questions/40752578/couchdb-views-c...
For your example specifically I'd use a proxy.
Do you propose to create proxy that parses query and estimates complexity? I think this task at least as hard as implementing couchdb myself (actually harder)
Is there any secure open source code with pouchdb/couchdb integrations?
As for queries, it kind of depends on your model. Mango queries are pretty limited (no joins, no arbitrary filters), so it's not necessarily as easy as you think to write one that hosed performance. A client could of course write one that doesn't use an index, which may or may not be a concern.
An easy option if it is though is just don't expose the `_find` endpoint, which effectively limits your users to the map/reduce queries you've written (unless you give them admin they don't have the ability to create their own).
I feel like your thinking about Couch as exposing your entire PostgreSQL DB to the internet, whereas with couch, a common model is to have a single database per user. In the Postgres model, providing the end user with any direct access is a nightmare, because every other users data is in there and I have to keep other users from viewing/modifying it. In Couch, you give them access to their database and only their database, that's how you isolate users.
[1]https://docs.couchdb.org/en/stable/intro/security.html
Mongo and postgress usually is not accessible for clients only for backend. Security handled by backend mostly and there is a plenty of resources how to implement secure server side applications which discusses attack vectors and how to make secure apps. Thankfully to this thread I’ve got few good ideas, that may help to design secure couchdb architecture (such as remove _find endpoint) but I’ve not seen any in-depth document about couchdb.
> I feel like your thinking about Couch as exposing your entire PostgreSQL DB to the internet
No, why do you think so?
One of the major selling point of couchdb is replication protocol for client-server data syncing. When you design product with posgress you don't allow to execute raw sql queries from clients without any application server. But looks like it is recommended way to update data in couchdb world if you want to have synchronisation. I can't understand how can this architecture be secure?