Skip to content

Commit

Permalink
Merge: nixos/postgresql: set up sandboxing (NixOS#344925)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ma27 authored Nov 2, 2024
2 parents d4f265a + 70a6092 commit 500d745
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 2 deletions.
5 changes: 5 additions & 0 deletions nixos/doc/manual/release-notes/rl-2411.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,11 @@

- `iproute2` now has libbpf support.

- `postgresql` is now [hardened by default](#module-services-postgres-hardening) using the common `systemd` settings for that.

If you use extensions that are not packaged in nixpkgs, please review whether it still works
with the current settings and adjust accordingly if needed.

- `nix.channel.enable = false` no longer implies `nix.settings.nix-path = []`.
Since Nix 2.13, a `nix-path` set in `nix.conf` cannot be overridden by the `NIX_PATH` configuration variable.

Expand Down
18 changes: 18 additions & 0 deletions nixos/modules/services/databases/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,24 @@ postgresql.withJIT.pname

evaluates to `"foobar"`.

## Service hardening {#module-services-postgres-hardening}

The service created by the [`postgresql`-module](#opt-services.postgresql.enable) uses
several common hardening options from `systemd`, most notably:

* Memory pages must not be both writable and executable (this only applies to non-JIT setups).
* A system call filter (see {manpage}`systemd.exec(5)` for details on `@system-service`).
* A stricter default UMask (`0027`).
* Only sockets of type `AF_INET`/`AF_INET6`/`AF_NETLINK`/`AF_UNIX` allowed.
* Restricted filesystem access (private `/tmp`, most of the file-system hierachy is mounted read-only, only process directories in `/proc` that are owned by the same user).

The NixOS module also contains necessary adjustments for extensions from `nixpkgs`
if these are enabled. If an extension or a postgresql feature from `nixpkgs` breaks
with hardening, it's considered a bug.

When using extensions that are not packaged in `nixpkgs`, hardening adjustments may
become necessary.

## Notable differences to upstream {#module-services-postgres-upstream-deviation}

- To avoid circular dependencies between default and -dev outputs, the output of the `pg_config` system view has been removed.
39 changes: 39 additions & 0 deletions nixos/modules/services/databases/postgresql.nix
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,46 @@ in
TimeoutSec = 120;

ExecStart = "${postgresql}/bin/postgres";

# Hardening
CapabilityBoundingSet = [ "" ];
DevicePolicy = "closed";
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "strict";
MemoryDenyWriteExecute = lib.mkDefault (cfg.settings.jit == "off");
NoNewPrivileges = true;
LockPersonality = true;
PrivateDevices = true;
PrivateMounts = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK" # used for network interface enumeration
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged @resources"
];
UMask = if groupAccessAvailable then "0027" else "0077";
}
(mkIf (cfg.dataDir != "/var/lib/postgresql") {
ReadWritePaths = [ cfg.dataDir ];
})
(mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") {
StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}";
StateDirectoryMode = if groupAccessAvailable then "0750" else "0700";
Expand Down
9 changes: 7 additions & 2 deletions nixos/tests/postgresql-wal-receiver.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ let
replicationUser = "wal_receiver_user";
replicationSlot = "wal_receiver_slot";
replicationConn = "postgresql://${replicationUser}@localhost";
baseBackupDir = "/tmp/pg_basebackup";
walBackupDir = "/tmp/pg_wal";
baseBackupDir = "/var/cache/wals/pg_basebackup";
walBackupDir = "/var/cache/wals/pg_wal";

recoveryFile = pkgs.writeTextDir "recovery.signal" "";

Expand All @@ -32,6 +32,10 @@ let
meta.maintainers = with lib.maintainers; [ pacien ];

nodes.machine = { ... }: {
systemd.tmpfiles.rules = [
"d /var/cache/wals 0750 postgres postgres - -"
];

services.postgresql = {
package = pkg;
enable = true;
Expand Down Expand Up @@ -60,6 +64,7 @@ let
# This is only to speedup test, it isn't time racing. Service is set to autorestart always,
# default 60sec is fine for real system, but is too much for a test
systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
systemd.services.postgresql.serviceConfig.ReadWritePaths = [ "/var/cache/wals" ];
};

testScript = ''
Expand Down
2 changes: 2 additions & 0 deletions nixos/tests/postgresql.nix
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ let
with subtest("Initdb works"):
machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2")
machine.log(machine.execute("systemd-analyze security postgresql.service | grep -v ✓")[1])
machine.shutdown()
'';

Expand Down

0 comments on commit 500d745

Please sign in to comment.