-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: add a short guide on security. #2201
Merged
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
--- | ||
title: Security - Guide | ||
description: >- | ||
How to secure data access and encrypt data with Electric. | ||
outline: [2, 3] | ||
--- | ||
|
||
<script setup> | ||
import ComponentsJPG from '/static/img/docs/guides/deployment/components.jpg?url' | ||
import ComponentsPNG from '/static/img/docs/guides/deployment/components.png?url' | ||
import ComponentsSmPNG from '/static/img/docs/guides/deployment/components.sm.png?url' | ||
</script> | ||
|
||
<img src="/img/icons/security.svg" class="product-icon" | ||
style="width: 72px" | ||
/> | ||
|
||
# Security | ||
|
||
How to secure data access and [encrypt data](#encryption) with Electric. | ||
|
||
## Data access | ||
|
||
Electric is a [sync service](/product/electric) that runs in front of Postgres. It connects to a Postgres database using a [`DATABASE_URL`](/docs/api/config#database-url) and exposes the data in that database via an [HTTP API](/docs/api/http). | ||
|
||
<figure> | ||
<a :href="ComponentsJPG"> | ||
<img :src="ComponentsPNG" class="hidden-sm" | ||
alt="Illustration of the main components of a successfull deployment" | ||
/> | ||
<img :src="ComponentsSmPNG" class="block-sm" | ||
style="max-width: 360px" | ||
alt="Illustration of the main components of a successfull deployment" | ||
/> | ||
</a> | ||
</figure> | ||
|
||
This API is [public by default](#public-by-default). It should be secured in production using [network security](#network-security) and/or an [authorization proxy](#authorization). | ||
|
||
### Public by default | ||
|
||
Electric connects to Postgres as a normal [database user](https://www.postgresql.org/docs/current/user-manag.html). It then exposes access to **any data** that its database user can access in Postgres to **any client** that can connect to the Electric HTTP API. | ||
|
||
You generally do _not_ want to expose public access to the contents of your database, so you **must** secure access to the Electric HTTP API. | ||
|
||
### Network security | ||
|
||
One way of securing access to Electric is to use a network firewall or IP whitelist. | ||
|
||
You can often configure this using the networking rules of your cloud provider. Or you can use these to restrict public access to Electric and only expose Electric via a reverse-proxy such as Nginx or Caddy. This reverse proxy can then enforce network security rules, for example, using Caddy's [`remote-ip` request matcher](https://caddyserver.com/docs/caddyfile/matchers#remote-ip): | ||
|
||
```hcl | ||
@denied not remote_ip 100.200.30.40 100.200.30.41 | ||
abort @denied | ||
``` | ||
|
||
This approach is useful when you're using Electric to sync into trusted infrastructure. However, it doesn't help when you're syncing data into client devices, like apps and web browsers. For those, you need to restrict access using an authorizing proxy. | ||
|
||
### Authorization | ||
|
||
Electric is designed to run behind an [authorizing proxy](/docs/guides/auth#requests-can-be-proxied). | ||
|
||
This is the primary method for securing data access to clients and apps and is documented in detail, with examples, in the [Auth guide](/docs/guides/auth). | ||
|
||
## Encryption | ||
|
||
Electric syncs ciphertext as well as it syncs plaintext. You can encrypt and decrypt data in HTTP middleware or in the local client. | ||
|
||
### End-to-end encryption | ||
|
||
For example, you can achieve end-to-end encryption by: | ||
|
||
- *encrypting* data before it leaves the client | ||
- *decrypting* data when it comes off the replication stream into the client | ||
|
||
You can see an example of this in the [encryption example](/demos/encryption): | ||
|
||
<<< @../../examples/encryption/src/Example.tsx{tsx} | ||
|
||
### Key management | ||
|
||
One of the primary challenges with encryption is key management. I.e.: choosing which data to encrypt with which keys and sharing the right keys with the right users. | ||
|
||
Electric doesn't provide or prescribe any specific key management solution. You're free to use any existing key management system, such as Hashicorp Vault, for key management. However, for end-to-end encryption, you will at some point need to get those keys to client. This is a job that Electric is good at: syncing the right data to the right users. | ||
|
||
For example, imagine you store keys in a seperate, extra secure, Postgres database and you segment your encryption by tenant (or group, or some other shared resource). You could sync keys to the client using a shape like this: | ||
|
||
```ts | ||
import { ShapeStream } from '@electric-sql/client' | ||
|
||
const stream = new ShapeStream({ | ||
url: `${ELECTRIC_URL}/v1/shape`, | ||
params: { | ||
table: 'tenants', | ||
columns: [ | ||
'keys' | ||
], | ||
where: `id in ('${user.tenant_ids.join(`', '`)}')` | ||
} | ||
}) | ||
``` | ||
|
||
You could then put a denormalised `tenant_id` column on all of the synced tables in your main database and lookup the correct key to use when decrypting and encrypting the row in the client. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a lot of experience with key distribution but isn't storing the key (unencrypted) alongside the encrypted data more-or-less make it basically the same as if it wasn't encrypted? Since anyone with access to the db can now decrypt whatever data they want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could store keys in a different database and just sync the right ones. I do think that the point of Electric being good to sync keys is valid: it's just like the distributed config case. You need to share the right keys with the right users. What better mechanism?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷 like I said I dunno — maybe if the key is encrypted before sharing so it's just a backup/cloud syncing mechanism.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have jigged the description a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately for e2e encryption you need to get keys into the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can have client-generated keys right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, but if you're sharing the data, you have to share keys.