vuls: init at 0.27.0
[NixPkgs.git] / nixos / tests / postgresql.nix
blobc0dd24cf6ad2ee0cd9121f043c1441f77ac3ba53
1 { system ? builtins.currentSystem,
2   config ? {},
3   pkgs ? import ../.. { inherit system config; }
4 }:
6 with import ../lib/testing-python.nix { inherit system pkgs; };
7 with pkgs.lib;
9 let
10   postgresql-versions = import ../../pkgs/servers/sql/postgresql pkgs;
11   test-sql = pkgs.writeText "postgresql-test" ''
12     CREATE EXTENSION pgcrypto; -- just to check if lib loading works
13     CREATE TABLE sth (
14       id int
15     );
16     INSERT INTO sth (id) VALUES (1);
17     INSERT INTO sth (id) VALUES (1);
18     INSERT INTO sth (id) VALUES (1);
19     INSERT INTO sth (id) VALUES (1);
20     INSERT INTO sth (id) VALUES (1);
21     CREATE TABLE xmltest ( doc xml );
22     INSERT INTO xmltest (doc) VALUES ('<test>ok</test>'); -- check if libxml2 enabled
23   '';
24   make-postgresql-test = postgresql-name: postgresql-package: backup-all: makeTest {
25     name = postgresql-name;
26     meta = with pkgs.lib.maintainers; {
27       maintainers = [ zagy ];
28     };
30     nodes.machine = {...}:
31       {
32         services.postgresql = {
33           enable = true;
34           package = postgresql-package;
35         };
37         services.postgresqlBackup = {
38           enable = true;
39           databases = optional (!backup-all) "postgres";
40         };
41       };
43     testScript = let
44       backupName = if backup-all then "all" else "postgres";
45       backupService = if backup-all then "postgresqlBackup" else "postgresqlBackup-postgres";
46       backupFileBase = "/var/backup/postgresql/${backupName}";
47     in ''
48       def check_count(statement, lines):
49           return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format(
50               statement, lines
51           )
54       machine.start()
55       machine.wait_for_unit("postgresql")
57       with subtest("Postgresql is available just after unit start"):
58           machine.succeed(
59               "cat ${test-sql} | sudo -u postgres psql"
60           )
62       with subtest("Postgresql survives restart (bug #1735)"):
63           machine.shutdown()
64           import time
65           time.sleep(2)
66           machine.start()
67           machine.wait_for_unit("postgresql")
69       machine.fail(check_count("SELECT * FROM sth;", 3))
70       machine.succeed(check_count("SELECT * FROM sth;", 5))
71       machine.fail(check_count("SELECT * FROM sth;", 4))
72       machine.succeed(check_count("SELECT xpath('/test/text()', doc) FROM xmltest;", 1))
74       with subtest("Backup service works"):
75           machine.succeed(
76               "systemctl start ${backupService}.service",
77               "zcat ${backupFileBase}.sql.gz | grep '<test>ok</test>'",
78               "ls -hal /var/backup/postgresql/ >/dev/console",
79               "stat -c '%a' ${backupFileBase}.sql.gz | grep 600",
80           )
81       with subtest("Backup service removes prev files"):
82           machine.succeed(
83               # Create dummy prev files.
84               "touch ${backupFileBase}.prev.sql{,.gz,.zstd}",
85               "chown postgres:postgres ${backupFileBase}.prev.sql{,.gz,.zstd}",
87               # Run backup.
88               "systemctl start ${backupService}.service",
89               "ls -hal /var/backup/postgresql/ >/dev/console",
91               # Since nothing has changed in the database, the cur and prev files
92               # should match.
93               "zcat ${backupFileBase}.sql.gz | grep '<test>ok</test>'",
94               "cmp ${backupFileBase}.sql.gz ${backupFileBase}.prev.sql.gz",
96               # The prev files with unused suffix should be removed.
97               "[ ! -f '${backupFileBase}.prev.sql' ]",
98               "[ ! -f '${backupFileBase}.prev.sql.zstd' ]",
100               # Both cur and prev file should only be accessible by the postgres user.
101               "stat -c '%a' ${backupFileBase}.sql.gz | grep 600",
102               "stat -c '%a' '${backupFileBase}.prev.sql.gz' | grep 600",
103           )
104       with subtest("Backup service fails gracefully"):
105           # Sabotage the backup process
106           machine.succeed("rm /run/postgresql/.s.PGSQL.5432")
107           machine.fail(
108               "systemctl start ${backupService}.service",
109           )
110           machine.succeed(
111               "ls -hal /var/backup/postgresql/ >/dev/console",
112               "zcat ${backupFileBase}.prev.sql.gz | grep '<test>ok</test>'",
113               "stat ${backupFileBase}.in-progress.sql.gz",
114           )
115           # In a previous version, the second run would overwrite prev.sql.gz,
116           # so we test a second run as well.
117           machine.fail(
118               "systemctl start ${backupService}.service",
119           )
120           machine.succeed(
121               "stat ${backupFileBase}.in-progress.sql.gz",
122               "zcat ${backupFileBase}.prev.sql.gz | grep '<test>ok</test>'",
123           )
126       with subtest("Initdb works"):
127           machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2")
129       machine.shutdown()
130     '';
132   };
134   mk-ensure-clauses-test = postgresql-name: postgresql-package: makeTest {
135     name = postgresql-name;
136     meta = with pkgs.lib.maintainers; {
137       maintainers = [ zagy ];
138     };
140     nodes.machine = {...}:
141       {
142         services.postgresql = {
143           enable = true;
144           package = postgresql-package;
145           ensureUsers = [
146             {
147               name = "all-clauses";
148               ensureClauses = {
149                 superuser = true;
150                 createdb = true;
151                 createrole = true;
152                 "inherit" = true;
153                 login = true;
154                 replication = true;
155                 bypassrls = true;
156               };
157             }
158             {
159               name = "default-clauses";
160             }
161           ];
162         };
163       };
165     testScript = let
166       getClausesQuery = user: pkgs.lib.concatStringsSep " "
167         [
168           "SELECT row_to_json(row)"
169           "FROM ("
170           "SELECT"
171             "rolsuper,"
172             "rolinherit,"
173             "rolcreaterole,"
174             "rolcreatedb,"
175             "rolcanlogin,"
176             "rolreplication,"
177             "rolbypassrls"
178           "FROM pg_roles"
179           "WHERE rolname = '${user}'"
180           ") row;"
181         ];
182     in ''
183       import json
184       machine.start()
185       machine.wait_for_unit("postgresql")
187       with subtest("All user permissions are set according to the ensureClauses attr"):
188           clauses = json.loads(
189             machine.succeed(
190                 "sudo -u postgres psql -tc \"${getClausesQuery "all-clauses"}\""
191             )
192           )
193           print(clauses)
194           assert clauses['rolsuper'], 'expected user with clauses to have superuser clause'
195           assert clauses['rolinherit'], 'expected user with clauses to have inherit clause'
196           assert clauses['rolcreaterole'], 'expected user with clauses to have create role clause'
197           assert clauses['rolcreatedb'], 'expected user with clauses to have create db clause'
198           assert clauses['rolcanlogin'], 'expected user with clauses to have login clause'
199           assert clauses['rolreplication'], 'expected user with clauses to have replication clause'
200           assert clauses['rolbypassrls'], 'expected user with clauses to have bypassrls clause'
202       with subtest("All user permissions default when ensureClauses is not provided"):
203           clauses = json.loads(
204             machine.succeed(
205                 "sudo -u postgres psql -tc \"${getClausesQuery "default-clauses"}\""
206             )
207           )
208           assert not clauses['rolsuper'], 'expected user with no clauses set to have default superuser clause'
209           assert clauses['rolinherit'], 'expected user with no clauses set to have default inherit clause'
210           assert not clauses['rolcreaterole'], 'expected user with no clauses set to have default create role clause'
211           assert not clauses['rolcreatedb'], 'expected user with no clauses set to have default create db clause'
212           assert clauses['rolcanlogin'], 'expected user with no clauses set to have default login clause'
213           assert not clauses['rolreplication'], 'expected user with no clauses set to have default replication clause'
214           assert not clauses['rolbypassrls'], 'expected user with no clauses set to have default bypassrls clause'
216       machine.shutdown()
217     '';
218   };
220   concatMapAttrs (name: package: {
221     ${name} = make-postgresql-test name package false;
222     ${name + "-backup-all"} = make-postgresql-test "${name + "-backup-all"}" package true;
223     ${name + "-clauses"} = mk-ensure-clauses-test name package;
224   }) postgresql-versions