Skip to content

Commit 0dcd1d8

Browse files
staaldraadhunleyd
andauthored
feat: add apparmor profile (#2087)
* feat: add apparmor profile * fix: split commands * Update ansible/tasks/setup-postgres.yml * feat: bump version numbers * fix: correct indent * chore: add tests for apparmor * chore: tests with superuser * chore: additional apparmor tests * chore: fix test for apparmor on service --------- Co-authored-by: Douglas J Hunley <doug.hunley@gmail.com>
1 parent c125c3d commit 0dcd1d8

5 files changed

Lines changed: 391 additions & 10 deletions

File tree

ansible/files/postgresql_config/postgresql.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ LimitNOFILE=16384
2424
{% if supabase_internal is defined %}
2525
ReadOnlyPaths=/etc
2626
InaccessiblePaths=/root -/var/lib/supabase -/var/lib/supabase-admin-agent -/var/cache/supabase-admin-agent -/opt/saltstack -/etc/salt
27+
AppArmorProfile=-sbpostgres
2728
{% endif %}
2829
[Install]
2930
WantedBy=multi-user.target
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#include <tunables/global>
2+
3+
# ============================================
4+
# POSTGRES PROFILE - With Supabase specific restrictions
5+
# ============================================
6+
profile sbpostgres flags=(attach_disconnected) {
7+
#include <abstractions/base>
8+
#include <abstractions/nameservice>
9+
#include <abstractions/openssl>
10+
11+
# Parent binary access to self
12+
/var/lib/postgresql/.nix-profile/bin/postgres mr,
13+
/nix/store/*/bin/.postgres-wrapped mr,
14+
/nix/store/*/bin/.postgres-wrapped ix,
15+
16+
# Wide open permissions for parent - to be tuned
17+
# some of this is managed via systemd sandboxing already
18+
/** rw,
19+
owner /** m,
20+
/ wr,
21+
/nix/store/** m,
22+
/etc r,
23+
/usr/local r,
24+
# lock permission for pgroonga
25+
/data/pgdata/pgroonga.log k,
26+
27+
# Systemd notification socket (for Type=notify services)
28+
/run/systemd/notify w,
29+
/{,var/}run/systemd/notify w,
30+
31+
# Allow disconnected paths (for mount namespaces)
32+
@{run}/systemd/notify w,
33+
/run/systemd/notify w,
34+
35+
# Full network access
36+
network inet stream,
37+
network inet6 stream,
38+
network unix stream,
39+
40+
# All capabilities
41+
capability,
42+
43+
# Libraries
44+
/lib/aarch64-linux-gnu/*.so* mr,
45+
/usr/lib/aarch64-linux-gnu/*.so* mr,
46+
/nix/store/*/lib/*.so* mr,
47+
48+
# safe commands
49+
/usr/bin/true ix,
50+
/usr/bin/false ix,
51+
# kill needed for postgresql to reload itself
52+
/bin/kill ix,
53+
54+
# When parent executes shell, transition to restricted profile
55+
# This accounts for popen, which postgres uses for any child process
56+
# Px = discrete profile transition (child gets different profile)
57+
/bin/sh Pix -> postgres_shell,
58+
/bin/bash Pix -> postgres_shell,
59+
/bin/dash Pix -> postgres_shell,
60+
/usr/bin/sh Pix -> postgres_shell,
61+
/usr/bin/dash Pix -> postgres_shell,
62+
/nix/store/*/bin/bash Pix -> postgres_shell,
63+
/usr/lib/postgresql/bin/pgsodium_getkey.sh Pix -> postgres_shell,
64+
/usr/bin/cat Pix -> postgres_shell,
65+
/bin/cat Pix -> postgres_shell,
66+
/usr/bin/admin-mgr Pix -> postgres_shell,
67+
/nix/store/*/bin/wal-g-2 Pix -> postgres_shell,
68+
/nix/store/*/bin/pgbackrest Pix -> postgres_shell,
69+
/nix/store/*/bin/pg_dump ix,
70+
/usr/bin/pgbackrest Pix -> pgbackrest_shell,
71+
/usr/bin/nix Pix -> pgbackrest_shell,
72+
/usr/bin/sudo Pix -> pgbackrest_shell,
73+
74+
profile postgres_shell {
75+
#include <abstractions/base>
76+
77+
/usr/bin/* m,
78+
/bin/* m,
79+
80+
# Shell binary
81+
/usr/bin/sh mr,
82+
/usr/bin/bash mr,
83+
/usr/bin/dash mr,
84+
/nix/store/*/bin/bash mr,
85+
86+
# Only allow specific commands to be executed from shell
87+
/usr/bin/cat ix,
88+
89+
# pgbackrest needs nix and sudo
90+
/usr/bin/nix ix,
91+
/usr/bin/sudo ix,
92+
93+
# backup things
94+
/usr/lib/postgresql/bin/pgsodium_getkey.sh ix,
95+
/usr/bin/admin-mgr ix,
96+
/nix/store/*/bin/.postgres-wrapped ix,
97+
/nix/store/*/bin/wal-g-2 ix,
98+
/nix/store/*/bin/pgbackrest ix,
99+
/nix/store/*/bin/pg_dump ix,
100+
101+
# file path permissions
102+
/** r,
103+
/data/wal_fetch_dir/ rw,
104+
/tmp/wal_fetch_dir/ rw,
105+
/var/lib/postgresql/data rw,
106+
/data/pgdata rw,
107+
/data/latest-lsn-checkpoint-v2 rw,
108+
/data/previous-lsn-checkpoint-v2 rw,
109+
/var/lib/postgresql/data/recovery.signal rw,
110+
/var/lib/postgresql/data/standby.signal rw,
111+
/var/lib/pgbackrest rw,
112+
/etc/pgbackrest/conf.d/** rw,
113+
/var/spool/pgbackrest/** rw,
114+
/var/log/pgbackrest/** rw,
115+
/etc/** r,
116+
/usr/local/** r,
117+
118+
119+
deny /var/lib/supabase/** rwx,
120+
deny /var/lib/supabase-admin-agent/** rwx,
121+
deny /var/cache/supabase-admin-agent/** rwx,
122+
deny /opt/saltstack/** rwx,
123+
deny /etc/salt/** rwx,
124+
deny /root wr,
125+
deny /home/** wr,
126+
# wal-g needs access to its own home directory
127+
/home/wal-g/* wr,
128+
129+
# Libraries
130+
/lib/aarch64-linux-gnu/*.so* mr,
131+
/usr/lib/aarch64-linux-gnu/*.so* mr,
132+
/nix/store/*/lib/*.so* mr,
133+
134+
# full network access
135+
# could further break this up so that only backup
136+
# tools have network access
137+
network,
138+
139+
# Block everything else
140+
deny /** x,
141+
}
142+
143+
profile pgbackrest_shell {
144+
#include <abstractions/base>
145+
146+
/usr/bin/* m,
147+
/bin/* m,
148+
149+
# Shell binary
150+
/usr/bin/sh mr,
151+
/usr/bin/bash mr,
152+
/usr/bin/dash mr,
153+
/nix/store/*/bin/bash mr,
154+
155+
# pgbackrest needs nix and sudo
156+
/usr/bin/nix ix,
157+
/usr/bin/sudo ix,
158+
/bin/bash ix,
159+
160+
/usr/bin/admin-mgr ix,
161+
/nix/store/*/bin/.postgres-wrapped ix,
162+
/nix/store/*/bin/pgbackrest ix,
163+
164+
# file path permissions
165+
/** r,
166+
/data/wal_fetch_dir/ rw,
167+
/tmp/wal_fetch_dir/ rw,
168+
/var/lib/postgresql/data rw,
169+
/data/pgdata rw,
170+
/data/latest-lsn-checkpoint-v2 rw,
171+
/data/previous-lsn-checkpoint-v2 rw,
172+
/var/lib/postgresql/data/recovery.signal rw,
173+
/var/lib/postgresql/data/standby.signal rw,
174+
/var/lib/pgbackrest rw,
175+
/etc/pgbackrest/conf.d/** rw,
176+
/var/spool/pgbackrest/** rw,
177+
/var/log/pgbackrest/** rw,
178+
/etc/** r,
179+
/usr/local/** r,
180+
181+
deny /var/lib/supabase/** rwx,
182+
deny /var/lib/supabase-admin-agent/** rwx,
183+
deny /var/cache/supabase-admin-agent/** rwx,
184+
deny /opt/saltstack/** rwx,
185+
deny /etc/salt/** rwx,
186+
deny /root wr,
187+
deny /home/** wr,
188+
189+
# Libraries
190+
/lib/aarch64-linux-gnu/*.so* mr,
191+
/usr/lib/aarch64-linux-gnu/*.so* mr,
192+
/nix/store/*/lib/*.so* mr,
193+
194+
# full network access
195+
# could further break this up so that only backup
196+
# tools have network access
197+
network,
198+
199+
# Block everything else
200+
deny /** x,
201+
}
202+
}

ansible/tasks/setup-postgres.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,22 @@
286286
when:
287287
- (is_psql_oriole or is_psql_17)
288288

289+
- name: copy PG apparmor profile
290+
ansible.builtin.copy:
291+
dest: '/etc/apparmor.d/sbpostgres'
292+
group: 'root'
293+
mode: '0644'
294+
owner: 'root'
295+
src: 'files/postgresql_config/sbpostgres_apparmor'
296+
297+
- name: parse apparmor sbpostgres profile
298+
ansible.builtin.command:
299+
cmd: '/usr/sbin/apparmor_parser -r /etc/apparmor.d/sbpostgres'
300+
301+
- name: reload apparmor with sbpostgres profile
302+
ansible.builtin.command:
303+
cmd: '/usr/sbin/aa-enforce sbpostgres'
304+
289305
- name: copy PG and optimizations systemd units
290306
ansible.builtin.template:
291307
dest: "/etc/systemd/system/{{ systemd_svc_item | basename }}"
@@ -376,7 +392,7 @@
376392
dest: '/var/lib/postgresql/.bashrc'
377393
line: "{{ lang_item }}"
378394
become: true
379-
loop:
395+
loop:
380396
- 'export LOCALE_ARCHIVE=/usr/lib/locale/locale-archive'
381397
- 'export LANG="en_US.UTF-8"'
382398
- 'export LANGUAGE="en_US.UTF-8"'

ansible/vars.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ postgres_major:
1010

1111
# Full version strings for each major version
1212
postgres_release:
13-
postgresorioledb-17: "17.6.0.063-orioledb"
14-
postgres17: "17.6.1.106"
15-
postgres15: "15.14.1.106"
13+
postgresorioledb-17: "17.6.0.064-orioledb"
14+
postgres17: "17.6.1.107"
15+
postgres15: "15.14.1.107"
1616

1717
# Non Postgres Extensions
1818
pgbouncer_release: 1.25.1

0 commit comments

Comments
 (0)