-
Notifications
You must be signed in to change notification settings - Fork 258
Add documentation on Row-Level Security MTA-5093 #3760
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
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
ae5978b
Create use-row-level-security-with-serverless-sql-database.md
fpagny 02daafa
Rename use-row-level-security-with-serverless-sql-database.md to use-…
fpagny 28709b1
docs(SDB): add documentation on Row-Level Security MTA-5093
SamyOubouaziz a27d785
docs(SDB): update
SamyOubouaziz d7d0302
Update use-row-level-security.mdx
fpagny 43e3c29
docs(SDB): update
SamyOubouaziz 4593502
docs(SDB): update
SamyOubouaziz 04fb904
docs(SDB): update
SamyOubouaziz 2307abb
docs(SDB): update
SamyOubouaziz 89f76ca
docs(SDB): update
SamyOubouaziz a8aec89
docs(SDB): update
SamyOubouaziz e78d515
docs(SDB): update
SamyOubouaziz de0722a
docs(SDB): update
SamyOubouaziz cf4396d
Apply suggestions from code review
SamyOubouaziz 6c4c658
Update serverless/sql-databases/api-cli/postgrest-row-level-security.mdx
SamyOubouaziz 1e6e60e
docs(SDB): update
SamyOubouaziz 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 hidden or 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
135 changes: 135 additions & 0 deletions
135
serverless/sql-databases/api-cli/postgrest-row-level-security.mdx
This file contains hidden or 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,135 @@ | ||
| --- | ||
| meta: | ||
| title: How to use Row-Level Security with PostgREST for Serverless SQL Databases | ||
| description: This page provides the steps to use Row-Level Security with PostGREST for Serverless SQL Databases | ||
| content: | ||
| h1: How to use Row-Level Security with PostgREST for Serverless SQL Databases | ||
| paragraph: This page provides the steps to use Row-Level Security with PostGREST for Serverless SQL Databases | ||
| tags: sql-databases serverless database row-level-security postgresql postgrest | ||
| dates: | ||
| validation: 2024-09-24 | ||
| posted: 2024-09-24 | ||
| categories: | ||
| - serverless | ||
| --- | ||
|
|
||
| PostgREST's built-in Row Level Security based on users JWT relies either on [role impersonation](https://docs.postgrest.org/en/v12/references/auth.html#user-impersonation) or [transaction-scoped settings](https://docs.postgrest.org/en/v12/references/transactions.html#tx-settings). | ||
|
|
||
| Due to connection pooling, Serverless SQL Databases currently only support transaction-scoped settings and requires using a single PostgreSQL role for all queries (the internal `role_readwrite` in PostgreSQL). | ||
|
|
||
| <Macro id="requirements" /> | ||
|
|
||
| <Macro id="requirements" /> | ||
|
|
||
| - A Scaleway account logged into the [console](https://console.scaleway.com) | ||
| - [Owner](/identity-and-access-management/iam/concepts/#owner) status or [IAM permissions](/identity-and-access-management/iam/concepts/#permission) allowing you to perform actions in the intended Organization | ||
| - [Created a Serverless SQL Database](/serverless/sql-databases/how-to/create-a-database/) | ||
|
|
||
| ## How to add sample data and enable PostgreSQL Row Level Security | ||
|
|
||
| 1. [Connect to your Serverless SQL Database](/serverless/sql-databases/quickstart/#how-to-connect-to-a-database) with a PostgreSQL client such as `psql`: | ||
| ```bash | ||
| psql "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require" | ||
| ``` | ||
|
|
||
| 2. Add sample data to the database using the following command: | ||
| ```sql | ||
| CREATE TABLE pets (name varchar, keeper varchar, id int); | ||
| INSERT INTO pets VALUES ('Stuart','role_admin',1),('Nemo','role_admin',2),('Alfie','role_readwrite',3),('Peanut','role_readwrite',4); | ||
| ``` | ||
|
|
||
| 3. Run the command below to enable **Row Level Security**: | ||
| ```sql | ||
| ALTER TABLE pets ENABLE row level security; | ||
| ``` | ||
|
|
||
| 4. Run the command below to create a PostgreSQL policy so that users or applications connecting with `role_readwrite` can access a `pet` row only if its `keeper` column value is `role_readwrite`: | ||
| ```sql | ||
| CREATE POLICY pets_keeper ON pets TO role_readwrite USING (keeper = current_user); | ||
| ``` | ||
|
|
||
| 5. (Optional) Run the command below to check that you can see all the data with your current connection: | ||
| ```sql | ||
| SELECT * FROM pets; | ||
| ``` | ||
| All the data in the database displays, as you are connected with `role_admin`. | ||
|
|
||
| <Message type="tip"> | ||
| You can verify the current role you are connected with using the following command: | ||
| ```sql | ||
| SELECT current_user; | ||
| ``` | ||
| </Message> | ||
|
|
||
| ## How to use Row Level Security with PostgREST | ||
|
|
||
| 1. Install PostgREST by following the [official documentation](https://docs.postgrest.org/en/v12/tutorials/tut0.html#step-1-install-postgresql). | ||
|
|
||
| 2. Create a `tutorial.conf` file with the following content: | ||
|
|
||
| ```json | ||
| db-uri = "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require" | ||
| db-schemas = "[your database schema]" | ||
| jwt-secret = "[your jwt secret]" | ||
| ``` | ||
|
|
||
| Where: | ||
| - `db-uri` must use credentials with an [application](/identity-and-access-management/iam/how-to/create-application/) having **ServerlessSQLDatabaseDataReadWrite** permissions (not **ServerlessSQLDatabaseReadWrite** or **ServerlessSQLDatabaseFullAccess**) | ||
| - `db-schemas` is your database schema. Use `public` as a default value. | ||
| - `jwt-secret` is a token generated using the following command: | ||
| ```sh | ||
| openssl rand -base64 32 | ||
| ``` | ||
|
|
||
| 3. In a terminal, access the folder containing the `tutorial.conf` file, and run the command below to start a local PostgREST instance: | ||
|
|
||
| ```bash | ||
| postgrest tutorial.conf | ||
| ``` | ||
|
|
||
| <Message type="tip"> | ||
| You can check that you can query your database by [generating a JWT](https://docs.postgrest.org/en/v12/tutorials/tut1.html#step-3-sign-a-token) with `{"role": "role_readwrite"}` as the payload data, then running the command below, where `$TOKEN` is your generated JWT: | ||
| ```bash | ||
| curl http://localhost:3000/pets \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| ``` | ||
| A list of pets displays. | ||
| </Message> | ||
|
|
||
| 4. Connect to your Serverless SQL Database with **ServerlessSQLDatabaseFullAccess** permissions, and run the following command to delete the `pets_keeper` policy previously applied to the `pets` table: | ||
| ```sql | ||
| DROP POLICY pets_keeper ON pets; | ||
| ``` | ||
|
|
||
| 5. Run the command below to create a new policy on the `pets` table: | ||
| ```sql | ||
| CREATE POLICY pets_keeper ON pets TO role_readwrite | ||
| USING (keeper = current_setting('request.jwt.claims', true)::json->>'user_type'); | ||
| ``` | ||
| This policy uses `current_setting` instead of `current_user`, and thus checks for additional fields contained by the JWT, and not only the `role` field. | ||
|
|
||
| 6. [Generate a JWT](https://docs.postgrest.org/en/v12/tutorials/tut1.html#step-3-sign-a-token) with the following payload data: | ||
| ```json | ||
| { | ||
| "role": "role_readwrite", | ||
| "user_type": "role_readwrite" | ||
| } | ||
| ``` | ||
| <Message type="tip"> | ||
| Here, the `user_type` value from the JWT will be checked against the `keeper` column value in your database to authorize access. You can replace `"user_type": "role_readwrite"` with any alternative field name or value depending on your use case. However, you must keep `"role": "role_readwrite"` for any users you want to authenticate through PostgREST, because other roles (such as `role_admin`) have too many permissions and will be able to see any data. | ||
| </Message> | ||
|
|
||
| 7. Run the command below to query your database using the JWT you just created through PostgREST: | ||
| ```bash | ||
| curl http://localhost:3000/pets \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| ``` | ||
| A list of pets with a `role_readwrite` value for `keeper` displays. | ||
|
|
||
| Your new application can now only access a specific subset of rows based on its permissions using transaction-scoped settings. | ||
|
|
||
| <Message type="tip"> | ||
| You can change your JWT payload data with `"user_type": "role_admin"` and see that only another set of rows will be displayed. | ||
|
|
||
| To go further, try adding fields or values to filter, and edit your policy to filter and give your policy a more complex set of rules. Refer to the [official PostgREST](https://docs.postgrest.org/en/v12/explanations/db_authz.html) documentation for more information. | ||
| </Message> | ||
90 changes: 90 additions & 0 deletions
90
serverless/sql-databases/how-to/use-row-level-security.mdx
This file contains hidden or 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,90 @@ | ||
| --- | ||
| meta: | ||
| title: How to use Row-Level Security with Serverless SQL Database | ||
| description: This page explains how to use Row-Level Security with Serverless SQL Databases | ||
| content: | ||
| h1: How to use Row-Level Security with Serverless SQL Database | ||
| paragraph: This page explains how to use Row-Level Security with Serverless SQL Databases | ||
| tags: sql-databases serverless database row-level-security postgresql postgrest | ||
| dates: | ||
| validation: 2024-09-24 | ||
| posted: 2024-09-24 | ||
| categories: | ||
| - serverless | ||
| --- | ||
|
|
||
| Row-Level Security is a database security mechanism that allows access only to specific rows of a table based on a user's role or permissions. | ||
|
|
||
| Row-Level Security can be activated with Serverless SQL Databases for a maximum of two different roles, having both read and write permissions. This can be used to restrict access to a subset of users with frameworks or tools such as [PostgREST](https://docs.postgrest.org/en/v12/). | ||
|
|
||
| This requires setting up different [IAM permissions sets](/identity-and-access-management/iam/reference-content/permission-sets/) for each role (**ServerlessSQLDatabaseFullAccess** or **ServerlessSQLDatabaseReadWrite** for one role, and **ServerlessSQLDatabaseDataReadWrite** for the other). | ||
|
|
||
| <Macro id="requirements" /> | ||
|
|
||
| - A Scaleway account logged into the [console](https://console.scaleway.com) | ||
| - [Owner](/identity-and-access-management/iam/concepts/#owner) status or [IAM permissions](/identity-and-access-management/iam/concepts/#permission) allowing you to perform actions in the intended Organization | ||
| - [Created a Serverless SQL Database](/serverless/sql-databases/how-to/create-a-database/) | ||
|
|
||
| ## How to add sample data and enable PostgreSQL Row Level Security | ||
|
|
||
| 1. [Connect to your Serverless SQL Database](/serverless/sql-databases/quickstart/#how-to-connect-to-a-database) with a PostgreSQL client such as `psql`: | ||
| ```bash | ||
| psql "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require" | ||
| ``` | ||
|
|
||
| 2. Add sample data to the database using the following command: | ||
| ```sql | ||
| CREATE TABLE pets (name varchar, keeper varchar, id int); | ||
| INSERT INTO pets VALUES ('Stuart','role_admin',1),('Nemo','role_admin',2),('Alfie','role_readwrite',3),('Peanut','role_readwrite',4); | ||
| ``` | ||
|
|
||
| 3. Run the command below to enable **Row-Level Security**: | ||
| ```sql | ||
| ALTER TABLE pets ENABLE row level security; | ||
| ``` | ||
|
|
||
| 4. Run the command below to create a PostgreSQL policy so that users or applications connecting with `role_readwrite` can access a `pet` row only if its `keeper` column value is `role_readwrite`: | ||
| ```sql | ||
| CREATE POLICY pets_keeper ON pets TO role_readwrite USING (keeper = current_user); | ||
| ``` | ||
|
|
||
| 5. (Optional) Run the command below to check that you can see all the data with your current connection: | ||
| ```sql | ||
| SELECT * FROM pets; | ||
| ``` | ||
| All the data contained in the database displays, as you are connected with `role_admin`. | ||
|
|
||
| <Message type="tip"> | ||
| You can verify the current role you are connected with using the following command: | ||
| ```sql | ||
| SELECT current_user; | ||
| ``` | ||
| </Message> | ||
|
|
||
| ## How to create an IAM application with Row Level Security enabled | ||
|
|
||
| 1. Create a new [IAM application](/identity-and-access-management/iam/how-to/create-application/). | ||
|
|
||
| 2. Create a new [IAM policy](/identity-and-access-management/iam/how-to/create-policy/), and add the **ServerlessSQLDatabaseDataReadWrite** permission set to the application you just created. | ||
|
|
||
| <Message type="note"> | ||
| You must provide **ServerlessSQLDatabaseDataReadWrite** permission set and not **ServerlessSQLDatabaseReadWrite** permission set. Indeed, all connections to your database performed with the former permissions set will use `role_readwrite` in PostgreSQL, whereas all connections performed with the latter, or **ServerlessSQLDatabaseFullAccess** will use `role_admin` in PostgreSQL. | ||
| </Message> | ||
|
|
||
| 3. Create an [API Key](/identity-and-access-management/iam/how-to/create-api-keys/) for this application, and connect to your Serverless SQL Database with this application. | ||
| ```bash | ||
| psql "postgres://[new-application-id]:[new-api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require" | ||
| ``` | ||
|
|
||
| 4. Run the following command to list the `pets` this application has access to: | ||
| ```sql | ||
| SELECT * FROM pets; | ||
| ``` | ||
| Only the pets with a `keeper` column value of `role_readwrite` display. Your new application can now only access a specific subset of rows based on its permissions. | ||
|
|
||
| <Message type="tip"> | ||
| Row-level security and policies can be created or deleted by a table owner. In this example, you can check the table owner with the following command: | ||
| ```sql | ||
| select * from pg_tables where tablename = 'pets'; | ||
| ``` | ||
| </Message> |
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.
Uh oh!
There was an error while loading. Please reload this page.