diff --git a/ansible/files/gandalf_config/gandalf.sudoers.conf b/ansible/files/gandalf_config/gandalf.sudoers.conf new file mode 100644 index 000000000..bf2517490 --- /dev/null +++ b/ansible/files/gandalf_config/gandalf.sudoers.conf @@ -0,0 +1,2 @@ +%gandalf ALL= NOPASSWD: /usr/bin/salt-call +%gandalf ALL= NOPASSWD: /usr/bin/gpg --homedir /etc/salt/gpgkeys --import, /usr/bin/gpg --homedir /etc/salt/gpgkeys --list-secret-keys * diff --git a/ansible/files/gandalf_config/gandalf_salt.service b/ansible/files/gandalf_config/gandalf_salt.service new file mode 100644 index 000000000..c70db7ed8 --- /dev/null +++ b/ansible/files/gandalf_config/gandalf_salt.service @@ -0,0 +1,19 @@ +[Unit] +Description=Configuration management via gandalf salt +After=network.target + +[Service] +Type=oneshot +ExecStart=/opt/gandalf/gandalf --config /opt/gandalf/config.yaml salt --apply --store-result +User=gandalf +Group=gandalf +StandardOutput=journal +StandardError=journal +StateDirectory=gandalf +CacheDirectory=gandalf + +# Security hardening +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/ansible/files/gandalf_config/gandalf_salt.timer b/ansible/files/gandalf_config/gandalf_salt.timer new file mode 100644 index 000000000..6862ca402 --- /dev/null +++ b/ansible/files/gandalf_config/gandalf_salt.timer @@ -0,0 +1,13 @@ +[Unit] +Description=Run Supabase gandalf salt on a schedule +Requires=gandalf_salt.service + +[Timer] +OnCalendar=*:0/10 +# Random delay up to 30 seconds splay +RandomizedDelaySec=30 +AccuracySec=1s +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/ansible/files/permission_check.py b/ansible/files/permission_check.py index a753f69ec..b34a56bb4 100644 --- a/ansible/files/permission_check.py +++ b/ansible/files/permission_check.py @@ -94,11 +94,17 @@ "systemd-coredump": [ {"groupname": "systemd-coredump", "username": "systemd-coredump"} ], + "gandalf": [ + {"groupname": "gandalf", "username": "gandalf"}, + {"groupname": "admin", "username": "gandalf"}, + {"groupname": "salt", "username": "gandalf"}, + ], } # 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 def run_osquery(query): @@ -154,6 +160,7 @@ 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 @@ -182,6 +189,7 @@ def check_postgresql_mount(): print("postgresql.service mounts /etc as read-only.") + def main(): parser = argparse.ArgumentParser( prog="Supabase Postgres Artifact Permissions Checker", @@ -234,6 +242,7 @@ def main(): "postgrest", "tcpdump", "systemd-coredump", + "gandalf", ] if not qemu_artifact: usernames.append("ec2-instance-connect") @@ -251,5 +260,6 @@ def main(): # Check if postgresql.service is using a read-only mount for /etc check_postgresql_mount() + if __name__ == "__main__": main() diff --git a/ansible/manifest-playbook.yml b/ansible/manifest-playbook.yml index 5c1c65053..583e3596c 100644 --- a/ansible/manifest-playbook.yml +++ b/ansible/manifest-playbook.yml @@ -61,6 +61,22 @@ shell: | cd /tmp && tar -cJf admin-mgr-{{ adminmgr_release }}-arm64.tar.xz admin-mgr + - name: Download gandalf archive + get_url: + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/gandalf/v{{ gandalf_release }}/gandalf_{{ gandalf_release }}_linux_arm64.tar.gz" + dest: "/tmp/gandalf.tar.gz" + timeout: 90 + + - name: gandalf - unpack archive in /tmp + unarchive: + remote_src: yes + src: /tmp/gandalf.tar.gz + dest: /tmp + + - name: gandalf - pack archive + shell: | + cd /tmp && tar -cJf gandalf-{{ gandalf_release }}-arm64.tar.xz gandalf + - name: upload archives shell: | aws s3 cp /tmp/{{ item.file }} s3://{{ internal_artifacts_bucket }}/upgrades/{{ item.service }}/{{ item.file }} @@ -73,3 +89,5 @@ file: supabase-admin-api-{{ adminapi_release }}-arm64.tar.xz - service: admin-mgr file: admin-mgr-{{ adminmgr_release }}-arm64.tar.xz + - service: gandalf + file: gandalf-{{ gandalf_release }}-arm64.tar.xz diff --git a/ansible/tasks/internal/gandalf.yml b/ansible/tasks/internal/gandalf.yml new file mode 100644 index 000000000..2c0d03fba --- /dev/null +++ b/ansible/tasks/internal/gandalf.yml @@ -0,0 +1,87 @@ +- name: gandalf - system group + group: + name: gandalf + system: yes + +- name: gandalf - system user + user: + name: gandalf + group: gandalf + groups: admin,salt + append: yes + system: yes + shell: /bin/sh + +- name: gandalf - config dir + file: + path: /opt/gandalf + owner: gandalf + state: directory + +- name: gandalf - gpg dir + file: + path: /etc/salt/gpgkeys + owner: root + group: salt + state: directory + +- name: give gandalf user permissions + copy: + src: files/gandalf_config/gandalf.sudoers.conf + dest: /etc/sudoers.d/gandalf + mode: "0644" + +- name: Setting arch (x86) + set_fact: + arch: "x86" + when: platform == "amd64" + +- name: Setting arch (arm) + set_fact: + arch: "arm64" + when: platform == "arm64" + +- name: Download gandalf archive + get_url: + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/gandalf/v{{ gandalf_release }}/gandalf-{{ gandalf_release }}-linux-{{ arch }}.tar.gz" + dest: "/tmp/gandalf.tar.gz" + timeout: 90 + +- name: gandalf - unpack archive in /opt + unarchive: + remote_src: yes + src: /tmp/gandalf.tar.gz + dest: /opt/gandalf/ + owner: gandalf + extra_opts: + - --strip-components=1 + +- name: gandalf - create symlink + ansible.builtin.file: + path: /opt/gandalf/gandalf + src: "/opt/gandalf/gandalf-linux-{{ arch }}" + state: link + owner: gandalf + mode: "0755" + force: yes + +- name: gandalf - create salt systemd timer file + copy: + src: files/gandalf_config/gandalf_salt.timer + dest: /etc/systemd/system/gandalf_salt.timer + +- name: gandalf - create salt service file + copy: + src: files/gandalf_config/gandalf_salt.service + dest: /etc/systemd/system/gandalf_salt.service + +- name: gandalf - reload systemd + systemd: + daemon_reload: yes + +# Initially ensure gandalf is installed but not started +- name: gandalf - DISABLE service + systemd: + name: gandalf_salt + enabled: no + state: stopped diff --git a/ansible/tasks/setup-supabase-internal.yml b/ansible/tasks/setup-supabase-internal.yml index 7aa931763..5a37dbaa0 100644 --- a/ansible/tasks/setup-supabase-internal.yml +++ b/ansible/tasks/setup-supabase-internal.yml @@ -115,5 +115,10 @@ tags: - aws-only +- name: Install gandalf + import_tasks: internal/gandalf.yml + tags: + - aws-only + - name: Envoy - use lds.supabase.yaml for /etc/envoy/lds.yaml command: mv /etc/envoy/lds.supabase.yaml /etc/envoy/lds.yaml diff --git a/ansible/vars.yml b/ansible/vars.yml index 2d6465832..939c892d1 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -9,9 +9,9 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.0.1.095-orioledb" - postgres17: "17.4.1.45" - postgres15: "15.8.1.102" + postgresorioledb-17: "17.0.1.096-orioledb" + postgres17: "17.4.1.046" + postgres15: "15.8.1.103" # Non Postgres Extensions pgbouncer_release: "1.19.0" @@ -57,3 +57,5 @@ adminmgr_release: 0.25.1 vector_x86_deb: "https://packages.timber.io/vector/0.22.3/vector_0.22.3-1_amd64.deb" vector_arm_deb: "https://packages.timber.io/vector/0.22.3/vector_0.22.3-1_arm64.deb" + +gandalf_release: 1.4.30