1{ lib, ... }:
2{
3 name = "postgrest";
4
5 meta = {
6 maintainers = with lib.maintainers; [ wolfgangwalther ];
7 };
8
9 nodes.machine =
10 {
11 config,
12 lib,
13 pkgs,
14 ...
15 }:
16 {
17 services.postgresql = {
18 enable = true;
19 initialScript = pkgs.writeText "init.sql" ''
20 CREATE ROLE postgrest LOGIN NOINHERIT;
21 CREATE ROLE anon ROLE postgrest;
22
23 CREATE ROLE postgrest_with_password LOGIN NOINHERIT PASSWORD 'password';
24 CREATE ROLE authenticated ROLE postgrest_with_password;
25 '';
26 };
27
28 services.postgrest = {
29 enable = true;
30 settings = {
31 admin-server-port = 3001;
32 db-anon-role = "anon";
33 db-uri.dbname = "postgres";
34 };
35 };
36
37 specialisation.withSecrets.configuration = {
38 services.postgresql.enableTCPIP = true;
39 services.postgrest = {
40 pgpassFile = "/run/secrets/.pgpass";
41 jwtSecretFile = "/run/secrets/jwt.secret";
42 settings.db-uri.host = "localhost";
43 settings.db-uri.user = "postgrest_with_password";
44 settings.server-port = 3000;
45 settings.server-unix-socket = null;
46 };
47 };
48 };
49
50 extraPythonPackages = p: [ p.pyjwt ];
51
52 testScript =
53 { nodes, ... }:
54 let
55 withSecrets = "${nodes.machine.system.build.toplevel}/specialisation/withSecrets";
56 in
57 ''
58 import jwt
59
60 machine.wait_for_unit("postgresql.target")
61
62 def wait_for_postgrest():
63 machine.wait_for_unit("postgrest.service")
64 machine.wait_until_succeeds("curl --fail -s http://localhost:3001/ready", timeout=30)
65
66 with subtest("anonymous access"):
67 wait_for_postgrest()
68 machine.succeed(
69 "curl --fail-with-body --no-progress-meter --unix-socket /run/postgrest/postgrest.sock http://localhost",
70 timeout=2
71 )
72
73 machine.execute("""
74 mkdir -p /run/secrets
75 echo "*:*:*:*:password" > /run/secrets/.pgpass
76 echo reallyreallyreallyreallyverysafe > /run/secrets/jwt.secret
77 """)
78
79 with subtest("authenticated access"):
80 machine.succeed("${withSecrets}/bin/switch-to-configuration test >&2")
81 wait_for_postgrest()
82 token = jwt.encode({ "role": "authenticated" }, "reallyreallyreallyreallyverysafe")
83 machine.succeed(
84 f"curl --fail-with-body --no-progress-meter -H 'Authorization: Bearer {token}' http://localhost:3000",
85 timeout=2
86 )
87 '';
88}