|
8 | 8 |
|
9 | 9 | </p>
|
10 | 10 |
|
11 |
| ---- |
| 11 | +## Installation |
12 | 12 |
|
13 |
| -**Documentation**: <a href="https://supabase.github.io/supautils" target="_blank">https://supabase.github.io/supautils</a> |
| 13 | +Tested to work on PostgreSQL 12, 13, 14 and 15. |
14 | 14 |
|
15 |
| -**Source Code**: <a href="https://github.com/supabase/supautils" target="_blank">https://github.com/supabase/supautils</a> |
| 15 | +## Setup |
16 | 16 |
|
17 |
| ---- |
| 17 | +Clone this repo and run |
18 | 18 |
|
19 |
| -`supautils` is a PostgreSQL extension providing: |
| 19 | +```bash |
| 20 | +make && make install |
| 21 | +``` |
20 | 22 |
|
21 |
| -- Enhanced [security](https://supabase.github.io/supautils/role_security/) for modifying roles. |
22 |
| -- Experimental/Unstable of the supabase hosted platform (behind setting flags) |
| 23 | +To make the extension available to the database add on `postgresql.conf`: |
| 24 | + |
| 25 | +``` |
| 26 | +shared_preload_libraries = 'supautils' |
| 27 | +``` |
| 28 | + |
| 29 | +## Role Security |
| 30 | + |
| 31 | +The supautils extension provides tooling to prevent non-superusers from modifying/granting a set of roles. |
| 32 | + |
| 33 | +Say your backend service depends on a `connector` role for connecting to the database. Also, you need to give database users the ability to create their own roles, i.e. they need the CREATEROLE privilege. |
| 34 | + |
| 35 | +A problem arises here, because any database user with CREATEROLE can DROP or ALTER the `connector` role, making your backend service fail. |
| 36 | +From [role attributes docs](https://www.postgresql.org/docs/current/role-attributes.html): |
| 37 | + |
| 38 | +> A role with CREATEROLE privilege can **alter and drop other roles, too, as well as grant or revoke membership in them**. |
| 39 | +> However, to create, alter, drop, or change membership of a superuser role, superuser status is required; |
| 40 | +> CREATEROLE is insufficient for that. |
| 41 | +
|
| 42 | +The above problem can be solved by configuring this extension to protect the `connector` role: |
| 43 | + |
| 44 | +``` |
| 45 | +supautils.reserved_roles = 'connector' |
| 46 | +``` |
| 47 | + |
| 48 | +This extension also allows restricting memberships grants for a set of roles. Certain default postgres roles are dangerous |
| 49 | +to expose to every database user. From [pg default roles](https://www.postgresql.org/docs/11/default-roles.html): |
| 50 | + |
| 51 | +> The pg_read_server_files, pg_write_server_files and pg_execute_server_program roles are intended to allow administrators to have trusted, |
| 52 | +> but non-superuser, roles which are able to access files and run programs on the database server as the user the database runs as. |
| 53 | +> As these roles are able to access any file on the server file system, they bypass all database-level permission checks when accessing files directly |
| 54 | +> and **they could be used to gain superuser-level access**, therefore great care should be taken when granting these roles to users. |
| 55 | +
|
| 56 | +For example, you can restrict doing `GRANT pg_read_server_files TO my_role` with: |
| 57 | + |
| 58 | +``` |
| 59 | +supautils.reserved_memberships = 'pg_read_server_files' |
| 60 | +``` |
| 61 | + |
| 62 | +### Configuration |
| 63 | + |
| 64 | +Settings available in `postgresql.conf`: |
| 65 | + |
| 66 | +#### Protect Roles |
| 67 | +``` |
| 68 | +supautils.reserved_roles = 'supabase_admin,supabase_auth_admin,supabase_storage_admin' |
| 69 | +``` |
| 70 | + |
| 71 | +#### Protect Memberships |
| 72 | +``` |
| 73 | +supautils.reserved_memberships = 'pg_read_server_files, pg_write_server_files, pg_execute_server_program' |
| 74 | +``` |
| 75 | + |
| 76 | +## Privileged Extensions |
| 77 | + |
| 78 | +This functionality is adapted from [pgextwlist](https://github.com/dimitri/pgextwlist). |
| 79 | + |
| 80 | +supautils allows you to let non-superusers manage extensions that would normally require being a superuser. e.g. the `hstore` extension creates a base type, which requires being a superuser to perform. |
| 81 | + |
| 82 | +To handle this, you can put the extension in `supautils.privileged_extensions`: |
| 83 | + |
| 84 | +``` |
| 85 | +supautils.privileged_extensions = 'hstore' |
| 86 | +supautils.privileged_extensions_superuser = 'postgres' |
| 87 | +``` |
| 88 | + |
| 89 | +Once you do, the extension creation will be delegated to the configured `supautils.privileged_extensions_superuser` (defaults to the bootstrap user, i.e. the role used to bootstrap the Postgres cluster). That means the `hstore` extension would be created as if by the superuser. |
| 90 | + |
| 91 | +Note that extension creation would behave normally (i.e. no delegation) if the current role is already a superuser. |
| 92 | + |
| 93 | +This also works for updating and dropping privileged extensions. |
| 94 | + |
| 95 | +If you don't want to enable this functionality, simply leave `supautils.privileged_extensions` empty. Extensions **not** in `supautils.privileged_extensions` would behave normally, i.e. created using the current role. |
| 96 | + |
| 97 | +supautils also lets you set custom scripts per privileged extension that gets run at certain events. Currently supported scripts are `before-create` and `after-create`. |
| 98 | + |
| 99 | +To make this work, configure the setting below: |
| 100 | + |
| 101 | +``` |
| 102 | +supautils.privileged_extensions_custom_scripts_path = '/opt/postgresql/privileged_extensions_custom_scripts' |
| 103 | +``` |
| 104 | + |
| 105 | +Then put the scripts inside the path, e.g.: |
| 106 | + |
| 107 | +```sql |
| 108 | +-- /opt/postgresql/privileged_extensions_custom_scripts/hstore/after-create.sql |
| 109 | +grant all on type hstore to non_superuser_role; |
| 110 | +``` |
| 111 | + |
| 112 | +This is useful for things like creating a dedicated role per extension and granting privileges as needed to that role. |
| 113 | + |
| 114 | +### Configuration |
| 115 | + |
| 116 | +Settings available in `postgresql.conf`: |
| 117 | + |
| 118 | +``` |
| 119 | +supautils.privileged_extensions = 'hstore,moddatetime' |
| 120 | +supautils.privileged_extensions_custom_scripts_path = '/opt/postgresql/privileged_extensions_custom_scripts' |
| 121 | +supautils.privileged_extensions_superuser = 'postgres' |
| 122 | +``` |
| 123 | + |
| 124 | +## Development |
| 125 | + |
| 126 | +[Nix](https://nixos.org/download.html) is required to set up the environment. |
| 127 | + |
| 128 | + |
| 129 | +### Testing |
| 130 | +For testing the module locally, execute: |
| 131 | + |
| 132 | +```bash |
| 133 | +# might take a while in downloading all the dependencies |
| 134 | +$ nix-shell |
| 135 | + |
| 136 | +# test on pg 12 |
| 137 | +$ supautils-with-pg-12 make installcheck |
| 138 | + |
| 139 | +# test on pg 13 |
| 140 | +$ supautils-with-pg-13 make installcheck |
| 141 | + |
| 142 | +# test on pg 14 |
| 143 | +$ supautils-with-pg-14 make installcheck |
| 144 | + |
| 145 | +# you can also test manually with |
| 146 | +$ supautils-with-pg-12 psql -U rolecreator |
| 147 | +``` |
0 commit comments