From 2d6268fb585e6b6fb9bc5db867c1644cd491651e Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Tue, 18 Feb 2025 11:03:51 +0100 Subject: [PATCH 1/6] feat: limit /etc to readonly https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#ReadWritePaths= Prevent postgres, or child-process of, from writing to /etc --- ansible/files/postgresql_config/postgresql.service.j2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ansible/files/postgresql_config/postgresql.service.j2 b/ansible/files/postgresql_config/postgresql.service.j2 index c056ac433..4cc138ec7 100644 --- a/ansible/files/postgresql_config/postgresql.service.j2 +++ b/ansible/files/postgresql_config/postgresql.service.j2 @@ -21,5 +21,8 @@ RestartSec=5 OOMScoreAdjust=-1000 EnvironmentFile=-/etc/environment.d/postgresql.env LimitNOFILE=16384 +{% if supabase_internal is defined %} +ReadOnlyPaths=/etc +{% endif %} [Install] WantedBy=multi-user.target From 0012206e2eff4f068785fca71d996c86b07ac10e Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Thu, 20 Feb 2025 12:53:37 +0100 Subject: [PATCH 2/6] bump version numbers --- ansible/vars.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/vars.yml b/ansible/vars.yml index 495b65858..13dfcc0d0 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -8,8 +8,8 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.0.1.051-orioledb" - postgres15: "15.8.1.058" + postgresorioledb-17: "17.0.1.052-orioledb.etcro" + postgres15: "15.8.1.059-rc.etcro" # Non Postgres Extensions pgbouncer_release: "1.19.0" From 393ca376bb5c9bfd956fcb9ab4d6c63f82f720d7 Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Fri, 21 Mar 2025 15:25:32 +0100 Subject: [PATCH 3/6] chore: add test for read-only mount --- ansible/files/permission_check.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ansible/files/permission_check.py b/ansible/files/permission_check.py index 5bf421018..123fcfb63 100644 --- a/ansible/files/permission_check.py +++ b/ansible/files/permission_check.py @@ -95,6 +95,8 @@ ], } +# postgresql.service is expected to mount /etc as read-only +expected_mount = "/etc ro" # This program depends on osquery being installed on the system # Function to run osquery @@ -151,6 +153,33 @@ def check_nixbld_users(): print("All nixbld users are in the 'nixbld' group.") +def check_postgresql_mount(): + # processes table has the nix .postgres-wrapped path as the + # binary path, rather than /usr/lib/postgresql/bin/postgres which + # is a symlink to /var/lib/postgresql/.nix-profile/bin/postgres, a script + # that ultimately calls /nix/store/...-postgresql-and-plugins-15.8/bin/.postgres-wrapped + query = """ + SELECT pid + FROM processes + WHERE path LIKE '%.postgres-wrapped%' + AND cmdline LIKE '%-D /etc/postgresql%'; + """ + query_result = run_osquery(query) + parsed_result = parse_json(query_result) + + pid = parsed_result[0].get("pid") + + # get the mounts for the process + with open(f"/proc/{pid}/mounts", "r") as o: + lines = [line for line in o if "/etc" in line and "ro," in line] + if len(lines) == 0: + print(f"Expected exactly 1 match, got 0") + sys.exit(1) + if len(lines) != 1: + print(f"Expected exactly 1 match, got {len(lines)}: {';'.join(lines)}") + sys.exit(1) + + print("postgresql.service mounts /etc as read-only.") def main(): parser = argparse.ArgumentParser( @@ -218,6 +247,8 @@ def main(): # Check if all nixbld users are in the nixbld group check_nixbld_users() + # Check if postgresql.service is using a read-only mount for /etc + check_postgresql_mount() if __name__ == "__main__": main() From e0708b685c7b768f8586fb4274488ac215977d18 Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Mon, 24 Mar 2025 12:02:28 +0100 Subject: [PATCH 4/6] start / stop postgresql.service when doing osquery permission checks --- ansible/playbook.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ansible/playbook.yml b/ansible/playbook.yml index 5c8a9f70e..222645c54 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -213,7 +213,9 @@ - name: Run osquery permission checks become: yes shell: | + systemctl start postgresql.service sudo -u ubuntu bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && /usr/bin/python3 /tmp/ansible-playbook/ansible/files/permission_check.py {{ '--qemu' if qemu_mode is defined else '' }}" + systemctl stop postgresql.service when: stage2_nix - name: Remove osquery From 1083e1fb05d93ce88ab75ddf408c4728fe935a4e Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 26 Mar 2025 07:44:38 -0400 Subject: [PATCH 5/6] chore: version suffix for local infra tests --- ansible/vars.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/vars.yml b/ansible/vars.yml index 1da5119dd..b2c824813 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -8,8 +8,8 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.0.1.054-orioledb" - postgres15: "15.8.1.061" + postgresorioledb-17: "17.0.1.054-orioledb-etc-1" + postgres15: "15.8.1.061-etc-1" # Non Postgres Extensions pgbouncer_release: "1.19.0" From 510474a0b00c0e526dae404d13ea36665e213e54 Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Wed, 9 Apr 2025 10:13:54 +0200 Subject: [PATCH 6/6] chore: bump versions --- ansible/vars.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ansible/vars.yml b/ansible/vars.yml index b2c824813..e2a2bafbc 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -4,12 +4,14 @@ async_mode: true postgres_major: - "15" + - "17" - "orioledb-17" # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.0.1.054-orioledb-etc-1" - postgres15: "15.8.1.061-etc-1" + postgresorioledb-17: "17.0.1.064-orioledb" + postgres17: "17.4.1.014" + postgres15: "15.8.1.071" # Non Postgres Extensions pgbouncer_release: "1.19.0"