Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/testinfra-ami-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
run: |
# TODO: use poetry for pkg mgmt
pip3 install boto3 "boto3-stubs[essential]" docker ec2instanceconnectcli pytest "pytest-testinfra[paramiko,docker]" requests
pytest -vv -s testinfra/test_ami_nix.py
pytest -vv -s testinfra/
- name: Cleanup resources on build cancellation
if: ${{ cancelled() }}
Expand Down
1 change: 1 addition & 0 deletions nix/checks.nix
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@
"extensions_schema" # tests extension loading
"roles" # includes roles/schemas from extensions not in CLI (pgtle, pgmq, repack, topology)
"pg_net_worker_privileges" # needs the authenticated/postgres roles from the full migrations, not present in the CLI prime file
"supautils_platform_policy" # needs the postgres role + primed hstore from the full migrations/prime, not present in the CLI variant
# Version-specific extension tests
"z_17_ext_interface"
"z_17_pg_stat_monitor"
Expand Down
62 changes: 62 additions & 0 deletions nix/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# nix/tests — pg_regress suite against the platform configuration

These tests run on every PR via `nix flake check` (see `nix/checks.nix`).
The `sql/` + `expected/` pairs are executed pg_regress-style against a
server started by `start-postgres-server` (`nix/tools/run-server.sh.in`),
which closely matches what ships on the AMI:

- the **rendered platform `supautils.conf`** is loaded
(`ansible/files/postgresql_config/supautils.conf.j2`, with only the
custom-scripts path substituted), and supautils is in
`session_preload_libraries`
- the **real migrations** run (`migrations/db`), so the platform role
topology exists: `postgres` (not a superuser), `anon`, `authenticated`,
`service_role`, the reserved roles, etc.
- the suite connects as `supabase_admin`, the bootstrap **superuser** of
the test cluster
- `prime.sql` pre-creates the platform extension set before any test runs

This means changes to `supautils.conf.j2` are live in this suite on the
same PR that makes them — conf changes and their tests should travel
together.

## Testing platform policy (supautils behavior for real roles)

Because the session user is a superuser (and superusers are exempt from
most supautils restrictions), policy tests must switch to the role the
policy targets:

```sql
set role postgres;
-- statements exercising the restriction / delegation / grant
reset role;
```

Conventions for policy tests:

- **Restore the primed state.** Tests share one cluster and run in
filename order; if you drop or alter something `prime.sql` created
(e.g. an extension), recreate it in its default state at the end of
your file.
- **Keep assertions version-agnostic** where extension versions are
involved — e.g. compare against `pg_available_extensions.default_version`
instead of printing a version number, or suppress version-bearing
NOTICEs with `set client_min_messages = warning`. Version-specific
behavior belongs in `z_<ver>_*.sql` files, which only run for that
Postgres major.
- **Regenerating expected output:** run the same server locally
(`nix run .#start-postgres-server -- --daemonize <major>`), apply your
sql file with `psql -U supabase_admin`, and use the output; or take the
`regression_output` artifact from the failed CI check.

Examples: `supautils_platform_policy.sql` (extension delegation) and
`supautils_reserved_roles.sql` (reserved-role protection, using the
BEGIN/SAVEPOINT pattern to recover from an expected error mid-file).

## What does NOT belong here

- supautils *logic* tests (all GUC modes, statement variants) — those
live in the supautils repo's own regress suite.
- Artifact wiring checks (is the conf present on the built AMI, services
up, apparmor) — those live in `testinfra/` and run against a real EC2
instance of the AMI.
43 changes: 43 additions & 0 deletions nix/tests/expected/supautils_platform_policy.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
-- Reference example for platform-policy tests (see nix/tests/README.md).
--
-- This suite runs against the rendered supautils.conf.j2 with the real
-- migrations applied, so supautils behavior can be asserted as the actual
-- platform roles. The session user (supabase_admin) is the cluster
-- superuser, so policy tests must SET ROLE to the role the policy targets.
-- the platform supautils config is loaded
show supautils.privileged_role;
supautils.privileged_role
---------------------------
supabase_privileged_role
(1 row)

-- postgres is not a superuser: supautils policies apply to it
select rolsuper from pg_roles where rolname = 'postgres';
rolsuper
----------
f
(1 row)

-- privileged extension creation is delegated to the configured superuser
-- for non-superusers (supautils.privileged_extensions +
-- supautils.privileged_extensions_superuser)
drop extension hstore;
set role postgres;
create extension hstore;
select count(*) = 1 as installed from pg_extension where extname = 'hstore';
installed
-----------
t
(1 row)

reset role;
-- the delegated create leaves the extension owned by the configured
-- superuser, same as the primed state
select rolname from pg_roles r
join pg_extension e on e.extowner = r.oid
where e.extname = 'hstore';
rolname
----------------
supabase_admin
(1 row)

28 changes: 28 additions & 0 deletions nix/tests/sql/supautils_platform_policy.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Reference example for platform-policy tests (see nix/tests/README.md).
--
-- This suite runs against the rendered supautils.conf.j2 with the real
-- migrations applied, so supautils behavior can be asserted as the actual
-- platform roles. The session user (supabase_admin) is the cluster
-- superuser, so policy tests must SET ROLE to the role the policy targets.

-- the platform supautils config is loaded
show supautils.privileged_role;

-- postgres is not a superuser: supautils policies apply to it
select rolsuper from pg_roles where rolname = 'postgres';

-- privileged extension creation is delegated to the configured superuser
-- for non-superusers (supautils.privileged_extensions +
-- supautils.privileged_extensions_superuser)
drop extension hstore;

set role postgres;
create extension hstore;
select count(*) = 1 as installed from pg_extension where extname = 'hstore';
reset role;

-- the delegated create leaves the extension owned by the configured
-- superuser, same as the primed state
select rolname from pg_roles r
join pg_extension e on e.extowner = r.oid
where e.extname = 'hstore';
Loading
Loading