Skip to content

Commit 503fad9

Browse files
committed
docs: add snippets of functionality
1 parent b226e28 commit 503fad9

File tree

2 files changed

+68
-20
lines changed

2 files changed

+68
-20
lines changed

META.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "supautils",
33
"abstract": "Unlock advanced Postgres features without granting SUPERUSER access",
4-
"description": "Loadable library that allows creating event triggers, publications, and other highly privileged database objects on cloud deployments where giving SUPERUSER rights to end users isn’t an option",
4+
"description": "Loadable library that securely allows creating event triggers, publications, extensions to non-superusers",
55
"version": "2.9.1",
66
"maintainer": [
77
"Steve Chavez <[email protected]>",

README.md

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# supautils
22

33
[![Coverage Status](https://coveralls.io/repos/github/supabase/supautils/badge.svg?branch=master)](https://coveralls.io/github/supabase/supautils?branch=master)
4+
![PostgreSQL version](https://img.shields.io/badge/postgresql-13+-blue.svg)
45

56
Supautils is an extension that unlocks advanced Postgres features without granting SUPERUSER access.
67

7-
It's a loadable library that allows creating event triggers, publications, and other highly privileged database objects on cloud deployments where giving SUPERUSER rights to end users isn’t an option.
8+
It's a loadable library that securely allows creating event triggers, publications, extensions to non-superusers. Built for cloud deployments where giving SUPERUSER rights to end users isn’t an option.
89

9-
It's managed entirely by configuration — no tables, functions, or security labels are added to your database. That makes upgrades effortless and lets you apply settings cluster-wide solely via `postgresql.conf`.
10-
11-
Tested to work on PostgreSQL 13, 14, 15, 16 and 17.
10+
Completely managed by configuration — no tables, functions, or security labels are added to your database. This makes upgrades effortless and lets you apply settings cluster-wide solely via `postgresql.conf`.
1211

1312
## Installation
1413

@@ -22,6 +21,7 @@ To make supautils available to the whole cluster, you can add the following to `
2221

2322
```
2423
shared_preload_libraries = 'supautils'
24+
supautils.privileged_role = 'your_privileged_role'
2525
```
2626

2727
Or to make it available only on some PostgreSQL roles use `session_preload_libraries`.
@@ -33,6 +33,10 @@ ALTER ROLE role1 SET session_preload_libraries TO 'supautils';
3333
## Features
3434

3535
- [Privileged Role](#privileged-role)
36+
- [Non-Superuser Publications](#non-superuser-publications)
37+
- [Non-Superuser Foreign Data Wrappers](#non-superuser-foreign-data-wrappers)
38+
- [Non-Superuser Settings](#non-superuser-settings)
39+
- [Non-Superuser Event Triggers](#non-superuser-event-triggers)
3640
- [Privileged extensions](#privileged-extensions)
3741
- [Constrained extensions](#constrained-extensions)
3842
- [Extensions Parameter Overrides](#extensions-parameter-overrides)
@@ -42,22 +46,57 @@ ALTER ROLE role1 SET session_preload_libraries TO 'supautils';
4246

4347
### Privileged Role
4448

45-
PostgreSQL doesn't allow non-superusers to create certain database objects like publications, foreign data wrappers or event triggers. supautils allows creating these by configuring a `supautils.privileged_role`.
46-
This role is a proxy role for a SUPERUSER, which is configured by `supautils.superuser` (defaults to the bootstrap user, i.e. the role used to bootstrap the Postgres cluster).
49+
The privileged role is a proxy role for a SUPERUSER, which is configured by `supautils.superuser` (defaults to the bootstrap user, i.e. the role used to start the Postgres cluster).
50+
51+
When the privileged role creates a superuser-only database object (like publications):
52+
53+
- supautils will switch the role to the `supautils.superuser`, allowing the operation and creating the database object.
54+
+ In cases like event triggers, it will add additional protections. See [Non-Superuser Event Triggers](#non-superuser-event-triggers).
55+
- It will change the ownership of the database object to the privileged role.
56+
- Finally, supautils will switch back to the privileged role.
57+
58+
### Non-Superuser Publications
59+
60+
The privileged role can create publications. Once created they will be owned by the privileged role.
4761

48-
#### Non-Superuser Publications
62+
```sql
63+
set role privileged_role;
64+
select current_setting('is_superuser');
65+
current_setting
66+
-----------------
67+
off
68+
(1 row)
4969

50-
The privileged role can create publications. When it executes `create publication`, supautils will detect the statement and:
70+
create publication p for all tables;
71+
CREATE PUBLICATION
5172

52-
- It will switch to the `supautils.superuser`, allowing the operation and creating the publication.
53-
- It will change the ownership of the publication to the privileged role.
54-
- Finally, it will switch back to the privileged role.
73+
drop publication p;
74+
DROP PUBLICATION
75+
```
5576

56-
#### Non-Superuser Foreign Data Wrappers
77+
### Non-Superuser Foreign Data Wrappers
5778

58-
The privileged role can also execute `create foreign data wrapper..`, the logic followed is analogous to publication creation.
79+
The privileged role can create FDWs.
5980

60-
#### Non-Superuser Event Triggers
81+
82+
```sql
83+
set role privileged_role;
84+
select current_setting('is_superuser');
85+
current_setting
86+
-----------------
87+
off
88+
(1 row)
89+
90+
create extension postgres_fdw;
91+
CREATE EXTENSION
92+
93+
create foreign data wrapper new_fdw
94+
handler postgres_fdw_handler
95+
validator postgres_fdw_validator;
96+
CREATE FOREIGN DATA WRAPPER
97+
```
98+
99+
### Non-Superuser Event Triggers
61100

62101
The privileged role is also able to create event triggers, while adding protection for privilege escalation.
63102

@@ -72,17 +111,24 @@ The skipping behavior can be logged by setting the `supautils.log_skipped_evtrig
72111
Superuser event triggers work as usual, with the additional restriction that the event trigger function must be owned by a superuser.
73112

74113
```sql
114+
set role privileged_role;
115+
select current_setting('is_superuser');
116+
current_setting
117+
-----------------
118+
off
119+
(1 row)
120+
75121
create event trigger evtrig on ddl_command_end
76122
execute procedure func(); -- func must be owned by the superuser
123+
CREATE EVENT TRIGGER
77124
```
78125

79126
The privileged role won't be able to ALTER or DROP a superuser event trigger.
80127

81128
> [!IMPORTANT]
82-
> Limitation: privileged role event triggers won't fire when creating publications, foreign data wrappers or extensions.
83-
> This is due to implementation details, since supautils has to switch to `supautils.superuser` when creating the above database objects, and we have to skip privileged role event triggers here to avoid privilege escalation.
129+
> Limitation: privileged role event triggers won't fire when creating publications, foreign data wrappers or extensions. See https://github.com/supabase/supautils/issues/123.
84130
85-
#### Non-Superuser Settings
131+
### Non-Superuser Settings
86132

87133
Certain settings like `session_replication_role` can only be set by superusers. The privileged role can be allowed to change these settings by listing them in:
88134

@@ -216,18 +262,20 @@ supautils.drop_trigger_grants = '{ "my_role": ["public.not_my_table", "public.al
216262

217263
### Reserved Roles
218264

265+
Reserved roles are meant to be used by managed services that connect to the database. They're protected from mutations by end users.
266+
219267
> [!IMPORTANT]
220268
> The CREATEROLE problem is solved starting from PostgreSQL 16.
221269
222-
Roles with the CREATEROLE privilege can ALTER, DROP or GRANT other roles without restrictions.
270+
Additionally it solves a problem with the CREATEROLE privilege. As it can ALTER, DROP or GRANT other roles without restrictions.
223271

224272
From [role attributes docs](https://www.postgresql.org/docs/15/role-attributes.html):
225273

226274
> A role with CREATEROLE privilege can **alter and drop other roles, too, as well as grant or revoke membership in them**.
227275
> However, to create, alter, drop, or change membership of a superuser role, superuser status is required;
228276
> CREATEROLE is insufficient for that.
229277
230-
The above problem can be solved by configuring this extension to protect a set of roles, using the `reserved_roles` setting.
278+
The above can be solved by configuring this extension to protect a set of roles, using the `reserved_roles` setting.
231279

232280
```
233281
supautils.reserved_roles = 'connector, storage_admin'

0 commit comments

Comments
 (0)