diff --git a/ansible/playbook.yml b/ansible/playbook.yml index 8aea9e4cba..9edb75307e 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -183,10 +183,11 @@ systemctl stop fail2ban.service - name: Run supascan baseline validation - when: stage2 and not qemu + when: stage2 become: yes shell: | - /bin/bash /tmp/ansible-playbook/ansible/files/supascan_ami.sh /tmp/ansible-playbook/audit-specs/baselines/ami-build-{{ platform }} + baseline={{ 'ami' if not qemu else 'qemu' }}-build-{{ platform }} + /bin/bash /tmp/ansible-playbook/ansible/files/supascan_ami.sh /tmp/ansible-playbook/audit-specs/baselines/$baseline - name: Remove supascan after validation when: stage2 diff --git a/ansible/tasks/internal/admin-api.yml b/ansible/tasks/internal/admin-api.yml index 4a4f691fe4..8159af1d56 100644 --- a/ansible/tasks/internal/admin-api.yml +++ b/ansible/tasks/internal/admin-api.yml @@ -7,7 +7,7 @@ - name: adminapi - system user ansible.builtin.user: name: adminapi - uid: 1006 + uid: "{{ 1006 if not qemu else 1007 }}" group: adminapi groups: admin,envoy,gotrue,kong,pgbouncer,postgres,postgrest,root,systemd-journal,vector,wal-g diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index d660a0fe25..fb32321749 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -1,7 +1,7 @@ - name: supabase-admin-agent - system group ansible.builtin.group: name: supabase-admin-agent - gid: 987 + gid: "{{ 987 if not qemu else 988 }}" system: yes - name: supabase-admin-agent - system user diff --git a/ansible/tasks/setup-envoy.yml b/ansible/tasks/setup-envoy.yml index a3a6c04e69..588b2bfb94 100644 --- a/ansible/tasks/setup-envoy.yml +++ b/ansible/tasks/setup-envoy.yml @@ -7,7 +7,7 @@ - name: Envoy - user ansible.builtin.user: name: envoy - uid: 1003 + uid: "{{ 1003 if not qemu else 1004 }}" group: envoy state: present diff --git a/ansible/tasks/setup-gotrue.yml b/ansible/tasks/setup-gotrue.yml index adbda82803..b3378de4d4 100644 --- a/ansible/tasks/setup-gotrue.yml +++ b/ansible/tasks/setup-gotrue.yml @@ -13,7 +13,7 @@ - name: Gotrue - system user ansible.builtin.user: name: gotrue - uid: 1001 + uid: "{{ 1001 if not qemu else 1002 }}" group: gotrue state: present diff --git a/ansible/tasks/setup-kong.yml b/ansible/tasks/setup-kong.yml index 85c17eaa83..f904fef365 100644 --- a/ansible/tasks/setup-kong.yml +++ b/ansible/tasks/setup-kong.yml @@ -7,7 +7,7 @@ - name: Kong - user ansible.builtin.user: name: kong - uid: 1004 + uid: "{{ 1004 if not qemu else 1005 }}" group: kong state: present diff --git a/ansible/tasks/setup-pgbouncer.yml b/ansible/tasks/setup-pgbouncer.yml index 34a9a94851..d76aa46b8e 100644 --- a/ansible/tasks/setup-pgbouncer.yml +++ b/ansible/tasks/setup-pgbouncer.yml @@ -8,7 +8,7 @@ - name: Create pgbouncer user ansible.builtin.user: name: 'pgbouncer' - uid: 1000 + uid: "{{ 1000 if not qemu else 1001 }}" comment: 'PgBouncer user' group: pgbouncer groups: 'postgres,ssl-cert' diff --git a/ansible/tasks/setup-postgrest.yml b/ansible/tasks/setup-postgrest.yml index 3912363cb2..a6ad947896 100644 --- a/ansible/tasks/setup-postgrest.yml +++ b/ansible/tasks/setup-postgrest.yml @@ -7,7 +7,7 @@ - name: PostgREST - user ansible.builtin.user: name: postgrest - uid: 1002 + uid: "{{ 1002 if not qemu else 1003 }}" group: postgrest state: present diff --git a/ansible/tasks/setup-supabase-internal.yml b/ansible/tasks/setup-supabase-internal.yml index d00605432c..66c4ff1975 100644 --- a/ansible/tasks/setup-supabase-internal.yml +++ b/ansible/tasks/setup-supabase-internal.yml @@ -22,7 +22,7 @@ - name: add vector system group ansible.builtin.group: name: vector - gid: 989 + gid: "{{ 989 if not qemu else 990 }}" system: yes - name: add vector system user diff --git a/ansible/tasks/setup-system.yml b/ansible/tasks/setup-system.yml index caf106e78e..e753046dde 100644 --- a/ansible/tasks/setup-system.yml +++ b/ansible/tasks/setup-system.yml @@ -4,7 +4,7 @@ - name: Create ubuntu primary group ansible.builtin.group: name: ubuntu - gid: 1014 + gid: "{{ 1014 if not qemu else 1000 }}" state: present - name: Create ubuntu user supplementary groups # noqa: explicit-identity-id @@ -19,7 +19,7 @@ - name: Create ubuntu user ansible.builtin.user: name: ubuntu - uid: 1007 + uid: "{{ 1007 if not qemu else 1000 }}" group: ubuntu groups: - adm diff --git a/audit-specs/baselines/qemu-build-arm64/files-postgres-config.yml b/audit-specs/baselines/qemu-build-arm64/files-postgres-config.yml new file mode 100644 index 0000000000..3b42dff244 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/files-postgres-config.yml @@ -0,0 +1,97 @@ +# File baseline: postgres-config +# PostgreSQL configuration files for AMI build +# Uses string names for owner/group (not numeric IDs) +file: + # Main PostgreSQL config directory + /etc/postgresql: + exists: true + filetype: directory + owner: postgres + group: postgres + mode: '0775' + /etc/postgresql/postgresql.conf: + exists: true + filetype: file + owner: root + group: root + mode: '0644' + /etc/postgresql/pg_hba.conf: + exists: true + filetype: file + owner: root + group: postgres + mode: '0664' + /etc/postgresql/pg_ident.conf: + exists: true + filetype: file + owner: root + group: postgres + mode: '0644' + /etc/postgresql/logging.conf: + exists: true + filetype: file + owner: root + group: postgres + mode: '0644' + + # Custom PostgreSQL config directory + /etc/postgresql-custom: + exists: true + filetype: directory + owner: postgres + group: postgres + mode: '0775' + # Note: platform-defaults.conf, pgsodium_root.key, custom-overrides.conf, and + # generated-optimizations.conf are created at deploy time (not during AMI build) + /etc/postgresql-custom/supautils.conf: + exists: true + filetype: file + owner: postgres + group: postgres + mode: '0664' + /etc/postgresql-custom/conf.d: + exists: true + filetype: directory + owner: postgres + group: postgres + mode: '0775' + /etc/postgresql-custom/wal-g.conf: + exists: true + filetype: file + owner: postgres + group: postgres + mode: '0664' + /etc/postgresql-custom/read-replica.conf: + exists: true + filetype: file + owner: postgres + group: postgres + mode: '0664' + + # Extension custom scripts directory + /etc/postgresql-custom/extension-custom-scripts: + exists: true + filetype: directory + owner: postgres + group: postgres + mode: '0775' + /etc/postgresql-custom/extension-custom-scripts/before-create.sql: + exists: true + filetype: file + owner: postgres + group: postgres + mode: '0775' + + # PostgREST config directory + /etc/postgrest: + exists: true + filetype: directory + owner: postgrest + group: postgrest + mode: '0775' + /etc/postgrest/base.conf: + exists: true + filetype: file + owner: postgrest + group: postgrest + mode: '0644' diff --git a/audit-specs/baselines/qemu-build-arm64/files-postgres-data.yml b/audit-specs/baselines/qemu-build-arm64/files-postgres-data.yml new file mode 100644 index 0000000000..66823b38b7 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/files-postgres-data.yml @@ -0,0 +1,19 @@ +# File baseline: postgres-data +# PostgreSQL data directory for AMI build +# Uses string names for owner/group (not numeric IDs) +file: + # PostgreSQL data directory + /var/lib/postgresql: + exists: true + filetype: directory + owner: postgres + group: postgres + mode: '0755' + # Note: /var/lib/postgresql/data is a symlink during AMI build (points to /data/...) + # The actual data directory is created at deploy time + /var/lib/postgresql/data: + exists: true + filetype: symlink + owner: root + group: root + mode: '0777' diff --git a/audit-specs/baselines/qemu-build-arm64/files-security.yml b/audit-specs/baselines/qemu-build-arm64/files-security.yml new file mode 100644 index 0000000000..176f14241b --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/files-security.yml @@ -0,0 +1,77 @@ +# File baseline: security +# Critical security-related files for AMI build +# Uses string names for owner/group (not numeric IDs) +file: + # fail2ban configuration directory + /etc/fail2ban: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + /etc/fail2ban/jail.local: + exists: true + filetype: file + owner: root + group: root + mode: '0644' + + # AppArmor + /etc/apparmor.d: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + + # UFW firewall + /etc/ufw: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + /etc/ufw/ufw.conf: + exists: true + filetype: file + owner: root + group: root + mode: '0644' + + # SSH configuration + /etc/ssh/sshd_config: + exists: true + filetype: file + owner: root + group: root + mode: '0644' + + # PAM configuration + /etc/pam.d: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + + # Sudoers + /etc/sudoers: + exists: true + filetype: file + owner: root + group: root + mode: '0440' + /etc/sudoers.d: + exists: true + filetype: directory + owner: root + group: root + mode: '0750' + + # Security limits + /etc/security/limits.conf: + exists: true + filetype: file + owner: root + group: root + mode: '0644' diff --git a/audit-specs/baselines/qemu-build-arm64/files-ssl.yml b/audit-specs/baselines/qemu-build-arm64/files-ssl.yml new file mode 100644 index 0000000000..8af6c0a5af --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/files-ssl.yml @@ -0,0 +1,30 @@ +# File baseline: ssl +# SSL certificate and key directories for AMI build +# Uses string names for owner/group (not numeric IDs) +file: + # System SSL directory + /etc/ssl: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + /etc/ssl/certs: + exists: true + filetype: directory + owner: root + group: root + mode: '0755' + /etc/ssl/private: + exists: true + filetype: directory + owner: root + group: postgres + mode: '0750' + /etc/ssl/openssl.cnf: + exists: true + filetype: file + owner: root + group: root + mode: '0644' + # Note: /etc/ssl/adminapi is created at deploy time, not during AMI build diff --git a/audit-specs/baselines/qemu-build-arm64/group.yml b/audit-specs/baselines/qemu-build-arm64/group.yml new file mode 100644 index 0000000000..a1e251775f --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/group.yml @@ -0,0 +1,103 @@ +# Group baseline for AMI build +# Exact IDs are checked only for groups pinned during provisioning +group: + # System groups + root: + exists: true + sudo: + exists: true + adm: + exists: true + admin: + exists: true + users: + exists: true + nogroup: + exists: true + ubuntu: + exists: true + gid: 1000 + + # PostgreSQL ecosystem + postgres: + exists: true + gid: 1002 + pgbouncer: + exists: true + gid: 1003 + pgbackrest: + exists: true + gid: 1005 + wal-g: + exists: true + gid: 1004 + ssl-cert: + exists: true + gid: 1001 + + # Supabase services + gotrue: + exists: true + gid: 1006 + postgrest: + exists: true + gid: 1007 + adminapi: + exists: true + gid: 1011 + kong: + exists: true + gid: 1009 + envoy: + exists: true + gid: 1008 + vector: + exists: true + gid: 990 + supabase-admin-agent: + exists: true + gid: 988 + + # System service groups + messagebus: + exists: true + systemd-network: + exists: true + systemd-resolve: + exists: true + systemd-timesync: + exists: true + systemd-journal: + exists: true + polkitd: + exists: true + tcpdump: + exists: true + _ssh: + exists: true + salt: + exists: true + + # Nix + nixbld: + exists: true + + # Other system groups + disk: + exists: true + tty: + exists: true + audio: + exists: true + video: + exists: true + plugdev: + exists: true + netdev: + exists: true + gid: 105 + lxd: + exists: true + gid: 101 + crontab: + exists: false diff --git a/audit-specs/baselines/qemu-build-arm64/kernel-param.yml b/audit-specs/baselines/qemu-build-arm64/kernel-param.yml new file mode 100644 index 0000000000..ecaecf0a1a --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/kernel-param.yml @@ -0,0 +1,11 @@ +# kernel-param baseline for AMI build +# Checks that critical kernel parameters haven't changed +kernel-param: + vm.page-cluster: + value: '3' # kernel default; assert to catch if kernel upgrade changes it + kernel.panic: + value: '10' # set by setup-system.yml + vm.panic_on_oom: + value: '1' # set by setup-system.yml + vm.swappiness: + value: '10' # intentionally lowered from kernel default (60) for DB + zswap diff --git a/audit-specs/baselines/qemu-build-arm64/mount.yml b/audit-specs/baselines/qemu-build-arm64/mount.yml new file mode 100644 index 0000000000..9f8d5108a6 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/mount.yml @@ -0,0 +1,31 @@ +# Mount baseline for AMI build +# Only checks that critical mounts exist with correct filesystem type +# Mount options vary by kernel version and environment - not checked +mount: + /: + exists: true + filesystem: ext4 + /boot/efi: + exists: true + filesystem: vfat + /dev: + exists: true + filesystem: devtmpfs + /dev/pts: + exists: true + filesystem: devpts + /dev/shm: + exists: true + filesystem: tmpfs + /proc: + exists: true + filesystem: proc + /run: + exists: true + filesystem: tmpfs + /sys: + exists: true + filesystem: sysfs + /sys/fs/cgroup: + exists: true + filesystem: cgroup2 diff --git a/audit-specs/baselines/qemu-build-arm64/package.yml b/audit-specs/baselines/qemu-build-arm64/package.yml new file mode 100644 index 0000000000..a516112731 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/package.yml @@ -0,0 +1,109 @@ +# Package baseline for AMI build +# Only checks that critical packages are installed - no version checks +# Version drift is expected between builds +package: + # Core system + bash: + installed: true + coreutils: + installed: true + systemd: + installed: true + systemd-sysv: + installed: true + apt: + installed: true + dpkg: + installed: true + + # Security + apparmor: + installed: true + apparmor-utils: + installed: true + auditd: + installed: false + fail2ban: + installed: true + ufw: + installed: true + nftables: + installed: true + ca-certificates: + installed: true + openssl: + installed: true + + # Networking + openssh-server: + installed: true + curl: + installed: true + wget: + installed: true + iproute2: + installed: true + + # Cloud + cloud-init: + installed: true + cloud-guest-utils: + installed: true + ec2-instance-connect: + installed: false + amazon-ec2-utils: + installed: true + + # PostgreSQL ecosystem (installed via nix, but system deps needed) + libpq5: + installed: true + + # Supabase components + vector: + installed: true + + # Build/runtime dependencies + locales: + installed: true + acl: + installed: true + sudo: + installed: true + logrotate: + installed: true + sysstat: + installed: true + acpid: + installed: false + at: + installed: false + cron: + installed: false + + # Grub/boot + grub-common: + installed: true + grub-efi-arm64: + installed: true + efibootmgr: + installed: false + initramfs-tools: + installed: true + + # Filesystem + e2fsprogs: + installed: true + gdisk: + installed: false + + # Python (needed for ansible and scripts) + python3: + installed: true + + # Compression + gzip: + installed: true + bzip2: + installed: false + xz-utils: + installed: true diff --git a/audit-specs/baselines/qemu-build-arm64/service.yml b/audit-specs/baselines/qemu-build-arm64/service.yml new file mode 100644 index 0000000000..d79ac1dea6 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/service.yml @@ -0,0 +1,136 @@ +# Service baseline for AMI build +# Only checks that critical services exist - not their enabled/running state during build +# Services are configured but many are stopped during AMI build process +service: + # Core system services (should be running during build) + cron: + enabled: false + running: false + cloud-config: + enabled: true + running: true + cloud-final: + enabled: true + running: true + cloud-init: + enabled: true + running: true + cloud-init-local: + enabled: true + running: true + systemd-resolved: + enabled: true + running: true + systemd-timesyncd: + enabled: false + running: false + ufw: + enabled: true + running: true + unattended-upgrades: + enabled: true + running: true + sysstat: + enabled: false + running: false + nix-daemon: + enabled: false + running: true + nftables: + enabled: false + running: true + ssh: + enabled: false + running: false + atd: + enabled: false + running: false + getty@tty1: + enabled: true + running: true + grub-common: + enabled: true + running: false + grub-initrd-fallback: + enabled: true + running: false + hibinit-agent: + enabled: false + running: false + ec2-instance-connect-harvest-hostkeys: + enabled: false + running: false + networkd-dispatcher: + enabled: false + running: false + systemd-pstore: + enabled: true + running: false + e2scrub_reap: + enabled: true + running: false + + # Supabase services - these are STOPPED during AMI build but should exist + # We check enabled: false because they're disabled during build + postgresql: + enabled: false + running: false + pgbouncer: + enabled: false + running: false + postgrest: + enabled: false + running: false + gotrue: + enabled: false + running: false + adminapi: + enabled: false + running: false + envoy: + enabled: false + running: false + vector: + enabled: false + running: false + postgres_exporter: + enabled: false + running: false + pg_egress_collect: + enabled: false + running: false + fail2ban: + enabled: false + running: false + auditd: + enabled: false + running: false + apparmor: + enabled: true + running: true + + # Services falseshould not be running + kong: + enabled: false + running: false + supabase-admin-agent_salt: + enabled: false + running: false + database_optimizations: + enabled: false + running: false + postgrest-optimizations: + enabled: false + running: false + NetworkManager: + enabled: false + running: false + firewalld: + enabled: false + running: false + iptables: + enabled: false + running: false + display-manager: + enabled: false + running: false diff --git a/audit-specs/baselines/qemu-build-arm64/user.yml b/audit-specs/baselines/qemu-build-arm64/user.yml new file mode 100644 index 0000000000..fa209f8897 --- /dev/null +++ b/audit-specs/baselines/qemu-build-arm64/user.yml @@ -0,0 +1,109 @@ +# User baseline for AMI build +# Exact IDs are checked only for accounts pinned during provisioning +user: + # System users + root: + exists: true + home: /root + shell: /bin/bash + ubuntu: + exists: true + home: /home/ubuntu + shell: /usr/bin/bash + uid: 1000 + gid: 1000 + nobody: + exists: true + shell: /usr/sbin/nologin + + # PostgreSQL ecosystem + postgres: + exists: true + home: /var/lib/postgresql + shell: /bin/bash + uid: 999 + gid: 1002 + pgbouncer: + exists: true + home: /home/pgbouncer + uid: 1001 + gid: 1003 + shell: /usr/sbin/nologin + pgbackrest: + exists: true + home: /var/lib/pgbackrest + uid: 995 + gid: 1005 + wal-g: + exists: true + home: /home/wal-g + uid: 996 + gid: 1004 + + # Supabase services + gotrue: + exists: true + home: /home/gotrue + uid: 1002 + gid: 1006 + postgrest: + exists: true + home: /home/postgrest + uid: 1003 + gid: 1007 + adminapi: + exists: true + home: /home/adminapi + uid: 1007 + gid: 1011 + kong: + exists: true + home: /home/kong + uid: 1005 + gid: 1009 + envoy: + exists: true + home: /home/envoy + uid: 1004 + gid: 1008 + vector: + exists: true + home: /var/lib/vector + uid: 994 + gid: 990 + supabase-admin-agent: + exists: true + home: /home/supabase-admin-agent + uid: 990 + gid: 988 + + # System service users + sshd: + exists: true + shell: /usr/sbin/nologin + messagebus: + exists: true + shell: /usr/sbin/nologin + systemd-network: + exists: true + shell: /usr/sbin/nologin + systemd-resolve: + exists: true + shell: /usr/sbin/nologin + systemd-timesync: + exists: true + shell: /usr/sbin/nologin + polkitd: + exists: true + shell: /usr/sbin/nologin + tcpdump: + exists: true + shell: /usr/sbin/nologin + _apt: + exists: true + shell: /usr/sbin/nologin + ec2-instance-connect: + exists: false + salt: + exists: true + shell: /usr/sbin/nologin diff --git a/qemu.pkr.hcl b/qemu.pkr.hcl index 8a8d5e309e..ab854240f0 100644 --- a/qemu.pkr.hcl +++ b/qemu.pkr.hcl @@ -91,6 +91,11 @@ build { destination = "/tmp/ansible-playbook" } + provisioner "file" { + source = "audit-specs" + destination = "/tmp/ansible-playbook" + } + provisioner "file" { source = "migrations" destination = "/tmp"