Skip to content

Commit c4b29c9

Browse files
SamyOubouazizfpagnyjcirinosclwy
authored
Add documentation on Row-Level Security MTA-5093 (#3760)
* Create use-row-level-security-with-serverless-sql-database.md Added a documentation with example on how to use Row Level Security with Serverless SQL Database * Rename use-row-level-security-with-serverless-sql-database.md to use-row-level-security.md Updated document name to fit standards. * docs(SDB): add documentation on Row-Level Security MTA-5093 * docs(SDB): update * Update use-row-level-security.mdx Add paragraph to explain how to use Row Level Security with PostgREST tool * docs(SDB): update * docs(SDB): update * docs(SDB): update * docs(SDB): update * docs(SDB): update * docs(SDB): update * docs(SDB): update * docs(SDB): update * Apply suggestions from code review Co-authored-by: Jessica <[email protected]> * Update serverless/sql-databases/api-cli/postgrest-row-level-security.mdx Co-authored-by: Jessica <[email protected]> * docs(SDB): update --------- Co-authored-by: fpagny <[email protected]> Co-authored-by: Jessica <[email protected]>
1 parent c99b36d commit c4b29c9

File tree

3 files changed

+235
-2
lines changed

3 files changed

+235
-2
lines changed

menu/navigation.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4027,12 +4027,16 @@
40274027
"label": "Manage user permissions for Serverless SQL Databases",
40284028
"slug": "manage-permissions"
40294029
},
4030+
{
4031+
"label": "Use Row-Level Security on a database",
4032+
"slug": "use-row-level-security"
4033+
},
40304034
{
40314035
"label": "Edit a Serverless SQL Database's autoscaling",
40324036
"slug": "configure-autoscaling"
40334037
},
40344038
{
4035-
"label": "How to manage backups for Serverless SQL Databases",
4039+
"label": "Manage backups for Serverless SQL Databases",
40364040
"slug": "manage-backups"
40374041
},
40384042
{
@@ -4056,6 +4060,10 @@
40564060
{
40574061
"label": "Securing connections using SSL/TLS",
40584062
"slug": "secure-connection-ssl-tls"
4063+
},
4064+
{
4065+
"label": "Using Row-Level Security with PostgREST",
4066+
"slug": "postgrest-row-level-security"
40594067
}
40604068
],
40614069
"label": "API/CLI",
@@ -5399,4 +5407,4 @@
53995407
],
54005408
"label": "Additional Services"
54015409
}
5402-
]
5410+
]
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
meta:
3+
title: How to use Row-Level Security with PostgREST for Serverless SQL Databases
4+
description: This page provides the steps to use Row-Level Security with PostGREST for Serverless SQL Databases
5+
content:
6+
h1: How to use Row-Level Security with PostgREST for Serverless SQL Databases
7+
paragraph: This page provides the steps to use Row-Level Security with PostGREST for Serverless SQL Databases
8+
tags: sql-databases serverless database row-level-security postgresql postgrest
9+
dates:
10+
validation: 2024-09-24
11+
posted: 2024-09-24
12+
categories:
13+
- serverless
14+
---
15+
16+
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).
17+
18+
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).
19+
20+
<Macro id="requirements" />
21+
22+
<Macro id="requirements" />
23+
24+
- A Scaleway account logged into the [console](https://console.scaleway.com)
25+
- [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
26+
- [Created a Serverless SQL Database](/serverless/sql-databases/how-to/create-a-database/)
27+
28+
## How to add sample data and enable PostgreSQL Row Level Security
29+
30+
1. [Connect to your Serverless SQL Database](/serverless/sql-databases/quickstart/#how-to-connect-to-a-database) with a PostgreSQL client such as `psql`:
31+
```bash
32+
psql "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require"
33+
```
34+
35+
2. Add sample data to the database using the following command:
36+
```sql
37+
CREATE TABLE pets (name varchar, keeper varchar, id int);
38+
INSERT INTO pets VALUES ('Stuart','role_admin',1),('Nemo','role_admin',2),('Alfie','role_readwrite',3),('Peanut','role_readwrite',4);
39+
```
40+
41+
3. Run the command below to enable **Row Level Security**:
42+
```sql
43+
ALTER TABLE pets ENABLE row level security;
44+
```
45+
46+
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`:
47+
```sql
48+
CREATE POLICY pets_keeper ON pets TO role_readwrite USING (keeper = current_user);
49+
```
50+
51+
5. (Optional) Run the command below to check that you can see all the data with your current connection:
52+
```sql
53+
SELECT * FROM pets;
54+
```
55+
All the data in the database displays, as you are connected with `role_admin`.
56+
57+
<Message type="tip">
58+
You can verify the current role you are connected with using the following command:
59+
```sql
60+
SELECT current_user;
61+
```
62+
</Message>
63+
64+
## How to use Row Level Security with PostgREST
65+
66+
1. Install PostgREST by following the [official documentation](https://docs.postgrest.org/en/v12/tutorials/tut0.html#step-1-install-postgresql).
67+
68+
2. Create a `tutorial.conf` file with the following content:
69+
70+
```json
71+
db-uri = "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require"
72+
db-schemas = "[your database schema]"
73+
jwt-secret = "[your jwt secret]"
74+
```
75+
76+
Where:
77+
- `db-uri` must use credentials with an [application](/identity-and-access-management/iam/how-to/create-application/) having **ServerlessSQLDatabaseDataReadWrite** permissions (not **ServerlessSQLDatabaseReadWrite** or **ServerlessSQLDatabaseFullAccess**)
78+
- `db-schemas` is your database schema. Use `public` as a default value.
79+
- `jwt-secret` is a token generated using the following command:
80+
```sh
81+
openssl rand -base64 32
82+
```
83+
84+
3. In a terminal, access the folder containing the `tutorial.conf` file, and run the command below to start a local PostgREST instance:
85+
86+
```bash
87+
postgrest tutorial.conf
88+
```
89+
90+
<Message type="tip">
91+
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:
92+
```bash
93+
curl http://localhost:3000/pets \
94+
-H "Authorization: Bearer $TOKEN"
95+
```
96+
A list of pets displays.
97+
</Message>
98+
99+
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:
100+
```sql
101+
DROP POLICY pets_keeper ON pets;
102+
```
103+
104+
5. Run the command below to create a new policy on the `pets` table:
105+
```sql
106+
CREATE POLICY pets_keeper ON pets TO role_readwrite
107+
USING (keeper = current_setting('request.jwt.claims', true)::json->>'user_type');
108+
```
109+
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.
110+
111+
6. [Generate a JWT](https://docs.postgrest.org/en/v12/tutorials/tut1.html#step-3-sign-a-token) with the following payload data:
112+
```json
113+
{
114+
"role": "role_readwrite",
115+
"user_type": "role_readwrite"
116+
}
117+
```
118+
<Message type="tip">
119+
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.
120+
</Message>
121+
122+
7. Run the command below to query your database using the JWT you just created through PostgREST:
123+
```bash
124+
curl http://localhost:3000/pets \
125+
-H "Authorization: Bearer $TOKEN"
126+
```
127+
A list of pets with a `role_readwrite` value for `keeper` displays.
128+
129+
Your new application can now only access a specific subset of rows based on its permissions using transaction-scoped settings.
130+
131+
<Message type="tip">
132+
You can change your JWT payload data with `"user_type": "role_admin"` and see that only another set of rows will be displayed.
133+
134+
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.
135+
</Message>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
meta:
3+
title: How to use Row-Level Security with Serverless SQL Database
4+
description: This page explains how to use Row-Level Security with Serverless SQL Databases
5+
content:
6+
h1: How to use Row-Level Security with Serverless SQL Database
7+
paragraph: This page explains how to use Row-Level Security with Serverless SQL Databases
8+
tags: sql-databases serverless database row-level-security postgresql postgrest
9+
dates:
10+
validation: 2024-09-24
11+
posted: 2024-09-24
12+
categories:
13+
- serverless
14+
---
15+
16+
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.
17+
18+
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/).
19+
20+
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).
21+
22+
<Macro id="requirements" />
23+
24+
- A Scaleway account logged into the [console](https://console.scaleway.com)
25+
- [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
26+
- [Created a Serverless SQL Database](/serverless/sql-databases/how-to/create-a-database/)
27+
28+
## How to add sample data and enable PostgreSQL Row Level Security
29+
30+
1. [Connect to your Serverless SQL Database](/serverless/sql-databases/quickstart/#how-to-connect-to-a-database) with a PostgreSQL client such as `psql`:
31+
```bash
32+
psql "postgres://[user-or-application-id]:[api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require"
33+
```
34+
35+
2. Add sample data to the database using the following command:
36+
```sql
37+
CREATE TABLE pets (name varchar, keeper varchar, id int);
38+
INSERT INTO pets VALUES ('Stuart','role_admin',1),('Nemo','role_admin',2),('Alfie','role_readwrite',3),('Peanut','role_readwrite',4);
39+
```
40+
41+
3. Run the command below to enable **Row-Level Security**:
42+
```sql
43+
ALTER TABLE pets ENABLE row level security;
44+
```
45+
46+
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`:
47+
```sql
48+
CREATE POLICY pets_keeper ON pets TO role_readwrite USING (keeper = current_user);
49+
```
50+
51+
5. (Optional) Run the command below to check that you can see all the data with your current connection:
52+
```sql
53+
SELECT * FROM pets;
54+
```
55+
All the data contained in the database displays, as you are connected with `role_admin`.
56+
57+
<Message type="tip">
58+
You can verify the current role you are connected with using the following command:
59+
```sql
60+
SELECT current_user;
61+
```
62+
</Message>
63+
64+
## How to create an IAM application with Row Level Security enabled
65+
66+
1. Create a new [IAM application](/identity-and-access-management/iam/how-to/create-application/).
67+
68+
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.
69+
70+
<Message type="note">
71+
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.
72+
</Message>
73+
74+
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.
75+
```bash
76+
psql "postgres://[new-application-id]:[new-api-secret-key]@[database-hostname]:5432/[database-name]?sslmode=require"
77+
```
78+
79+
4. Run the following command to list the `pets` this application has access to:
80+
```sql
81+
SELECT * FROM pets;
82+
```
83+
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.
84+
85+
<Message type="tip">
86+
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:
87+
```sql
88+
select * from pg_tables where tablename = 'pets';
89+
```
90+
</Message>

0 commit comments

Comments
 (0)