Skip to content

Commit 97a911e

Browse files
authored
Merge: nixos/postgresql: extension based hardening relaxation (#355010)
2 parents 319acd0 + 68d9643 commit 97a911e

File tree

11 files changed

+93
-54
lines changed

11 files changed

+93
-54
lines changed

nixos/modules/services/databases/postgresql.nix

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
let
44
inherit (lib)
5+
any
56
attrValues
67
concatMapStrings
78
concatStringsSep
89
const
910
elem
1011
escapeShellArgs
1112
filterAttrs
13+
getName
1214
isString
1315
literalExpression
1416
mapAttrs
@@ -31,19 +33,19 @@ let
3133

3234
cfg = config.services.postgresql;
3335

34-
postgresql =
35-
let
36-
# ensure that
37-
# services.postgresql = {
38-
# enableJIT = true;
39-
# package = pkgs.postgresql_<major>;
40-
# };
41-
# works.
42-
base = if cfg.enableJIT then cfg.package.withJIT else cfg.package.withoutJIT;
43-
in
44-
if cfg.extraPlugins == []
45-
then base
46-
else base.withPackages cfg.extraPlugins;
36+
# ensure that
37+
# services.postgresql = {
38+
# enableJIT = true;
39+
# package = pkgs.postgresql_<major>;
40+
# };
41+
# works.
42+
basePackage = if cfg.enableJIT
43+
then cfg.package.withJIT
44+
else cfg.package.withoutJIT;
45+
46+
postgresql = if cfg.extensions == []
47+
then basePackage
48+
else basePackage.withPackages cfg.extensions;
4749

4850
toStr = value:
4951
if true == value then "yes"
@@ -61,6 +63,8 @@ let
6163

6264
groupAccessAvailable = versionAtLeast postgresql.version "11.0";
6365

66+
extensionNames = map getName postgresql.installedExtensions;
67+
extensionInstalled = extension: elem extension extensionNames;
6468
in
6569

6670
{
@@ -69,6 +73,7 @@ in
6973

7074
(mkRenamedOptionModule [ "services" "postgresql" "logLinePrefix" ] [ "services" "postgresql" "settings" "log_line_prefix" ])
7175
(mkRenamedOptionModule [ "services" "postgresql" "port" ] [ "services" "postgresql" "settings" "port" ])
76+
(mkRenamedOptionModule [ "services" "postgresql" "extraPlugins" ] [ "services" "postgresql" "extensions" ])
7277
];
7378

7479
###### interface
@@ -372,12 +377,12 @@ in
372377
'';
373378
};
374379

375-
extraPlugins = mkOption {
380+
extensions = mkOption {
376381
type = with types; coercedTo (listOf path) (path: _ignorePg: path) (functionTo (listOf path));
377382
default = _: [];
378383
example = literalExpression "ps: with ps; [ postgis pg_repack ]";
379384
description = ''
380-
List of PostgreSQL plugins.
385+
List of PostgreSQL extensions to install.
381386
'';
382387
};
383388

@@ -639,7 +644,7 @@ in
639644
PrivateTmp = true;
640645
ProtectHome = true;
641646
ProtectSystem = "strict";
642-
MemoryDenyWriteExecute = lib.mkDefault (cfg.settings.jit == "off");
647+
MemoryDenyWriteExecute = lib.mkDefault (cfg.settings.jit == "off" && (!any extensionInstalled [ "plv8" ]));
643648
NoNewPrivileges = true;
644649
LockPersonality = true;
645650
PrivateDevices = true;
@@ -663,10 +668,12 @@ in
663668
RestrictRealtime = true;
664669
RestrictSUIDSGID = true;
665670
SystemCallArchitectures = "native";
666-
SystemCallFilter = [
667-
"@system-service"
668-
"~@privileged @resources"
669-
];
671+
SystemCallFilter =
672+
[
673+
"@system-service"
674+
"~@privileged @resources"
675+
]
676+
++ lib.optionals (any extensionInstalled [ "plv8" ]) [ "@pkey" ];
670677
UMask = if groupAccessAvailable then "0027" else "0077";
671678
}
672679
(mkIf (cfg.dataDir != "/var/lib/postgresql") {

nixos/modules/services/web-apps/immich.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ in
227227
ensureClauses.login = true;
228228
}
229229
];
230-
extraPlugins = ps: with ps; [ pgvecto-rs ];
230+
extensions = ps: with ps; [ pgvecto-rs ];
231231
settings = {
232232
shared_preload_libraries = [ "vectors.so" ];
233233
search_path = "\"$user\", public, vectors";

nixos/modules/services/web-apps/mobilizon.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ in
383383
ensureDBOwnership = false;
384384
}
385385
];
386-
extraPlugins = ps: with ps; [ postgis ];
386+
extensions = ps: with ps; [ postgis ];
387387
};
388388

389389
# Nginx config taken from support/nginx/mobilizon-release.conf

nixos/tests/postgresql/anonymizer.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ let
2020
inherit package;
2121
enable = true;
2222
enableJIT = lib.hasInfix "-jit-" package.name;
23-
extraPlugins = ps: [ ps.anonymizer ];
23+
extensions = ps: [ ps.anonymizer ];
2424
settings.shared_preload_libraries = [ "anon" ];
2525
};
2626
};

nixos/tests/postgresql/pgjwt.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ let
2424
inherit package;
2525
enable = true;
2626
enableJIT = lib.hasInfix "-jit-" package.name;
27-
extraPlugins =
27+
extensions =
2828
ps: with ps; [
2929
pgjwt
3030
pgtap

nixos/tests/postgresql/pgvecto-rs.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ let
3838
inherit package;
3939
enable = true;
4040
enableJIT = lib.hasInfix "-jit-" package.name;
41-
extraPlugins =
41+
extensions =
4242
ps: with ps; [
4343
pgvecto-rs
4444
];

nixos/tests/postgresql/postgresql.nix

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,59 @@ let
1414
postgresql-clauses = makeEnsureTestFor package;
1515
};
1616

17-
test-sql = pkgs.writeText "postgresql-test" ''
18-
CREATE EXTENSION pgcrypto; -- just to check if lib loading works
19-
CREATE TABLE sth (
20-
id int
17+
test-sql =
18+
enablePLv8Test:
19+
pkgs.writeText "postgresql-test" (
20+
''
21+
CREATE EXTENSION pgcrypto; -- just to check if lib loading works
22+
CREATE TABLE sth (
23+
id int
24+
);
25+
INSERT INTO sth (id) VALUES (1);
26+
INSERT INTO sth (id) VALUES (1);
27+
INSERT INTO sth (id) VALUES (1);
28+
INSERT INTO sth (id) VALUES (1);
29+
INSERT INTO sth (id) VALUES (1);
30+
CREATE TABLE xmltest ( doc xml );
31+
INSERT INTO xmltest (doc) VALUES ('<test>ok</test>'); -- check if libxml2 enabled
32+
''
33+
+ lib.optionalString enablePLv8Test ''
34+
-- check if hardening gets relaxed
35+
CREATE EXTENSION plv8;
36+
-- try to trigger the V8 JIT, which requires MemoryDenyWriteExecute
37+
DO $$
38+
let xs = [];
39+
for (let i = 0, n = 400000; i < n; i++) {
40+
xs.push(Math.round(Math.random() * n))
41+
}
42+
console.log(xs.reduce((acc, x) => acc + x, 0));
43+
$$ LANGUAGE plv8;
44+
''
2145
);
22-
INSERT INTO sth (id) VALUES (1);
23-
INSERT INTO sth (id) VALUES (1);
24-
INSERT INTO sth (id) VALUES (1);
25-
INSERT INTO sth (id) VALUES (1);
26-
INSERT INTO sth (id) VALUES (1);
27-
CREATE TABLE xmltest ( doc xml );
28-
INSERT INTO xmltest (doc) VALUES ('<test>ok</test>'); -- check if libxml2 enabled
29-
'';
3046

3147
makeTestForWithBackupAll =
3248
package: backupAll:
49+
let
50+
enablePLv8Check = !package.pkgs.plv8.meta.broken;
51+
in
3352
makeTest {
3453
name = "postgresql${lib.optionalString backupAll "-backup-all"}-${package.name}";
3554
meta = with lib.maintainers; {
3655
maintainers = [ zagy ];
3756
};
3857

3958
nodes.machine =
40-
{ ... }:
59+
{ config, ... }:
4160
{
4261
services.postgresql = {
4362
inherit package;
4463
enable = true;
4564
enableJIT = lib.hasInfix "-jit-" package.name;
65+
# plv8 doesn't support postgresql with JIT, so we only run the test
66+
# for the non-jit variant.
67+
# TODO(@Ma27) split this off into its own VM test and move a few other
68+
# extension tests to use postgresqlTestExtension.
69+
extensions = lib.mkIf enablePLv8Check (ps: with ps; [ plv8 ]);
4670
};
4771

4872
services.postgresqlBackup = {
@@ -69,7 +93,7 @@ let
6993
7094
with subtest("Postgresql is available just after unit start"):
7195
machine.succeed(
72-
"cat ${test-sql} | sudo -u postgres psql"
96+
"cat ${test-sql enablePLv8Check} | sudo -u postgres psql"
7397
)
7498
7599
with subtest("Postgresql survives restart (bug #1735)"):

nixos/tests/postgresql/timescaledb.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ let
5454
inherit package;
5555
enable = true;
5656
enableJIT = lib.hasInfix "-jit-" package.name;
57-
extraPlugins =
57+
extensions =
5858
ps: with ps; [
5959
timescaledb
6060
timescaledb_toolkit

nixos/tests/postgresql/tsja.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let
2121
inherit package;
2222
enable = true;
2323
enableJIT = lib.hasInfix "-jit-" package.name;
24-
extraPlugins =
24+
extensions =
2525
ps: with ps; [
2626
tsja
2727
];

nixos/tests/postgresql/wal2json.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let
1717
inherit package;
1818
enable = true;
1919
enableJIT = lib.hasInfix "-jit-" package.name;
20-
extraPlugins = with package.pkgs; [ wal2json ];
20+
extensions = with package.pkgs; [ wal2json ];
2121
settings = {
2222
wal_level = "logical";
2323
max_replication_slots = "10";

0 commit comments

Comments
 (0)