From 42f9c5b5688e9db03ef4bf238ca1de4fdc6658dc Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Fri, 27 Jun 2025 18:53:40 +0100 Subject: [PATCH 1/6] feat: add the supabase admin agent to the ami build --- .github/workflows/nix-build.yml | 10 +-- .github/workflows/testinfra-ami-build.yml | 14 +-- ansible/files/permission_check.py | 10 +++ .../supabase-admin-agent.sudoers.conf | 2 + .../supabase-admin-agent_salt.service | 19 ++++ .../supabase-admin-agent_salt.timer | 13 +++ .../tasks/internal/supabase-admin-agent.yml | 87 +++++++++++++++++++ ansible/tasks/setup-supabase-internal.yml | 17 ++-- ansible/vars.yml | 7 +- 9 files changed, 158 insertions(+), 21 deletions(-) create mode 100644 ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf create mode 100644 ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service create mode 100644 ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer create mode 100644 ansible/tasks/internal/supabase-admin-agent.yml diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index d562ab6ca..36dc01d05 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -79,19 +79,19 @@ jobs: trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI=% cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= - name: Build psql bundle run: > - nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48" - -- --skip-cached --no-nom - --flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')" + nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48" + -- --skip-cached --no-nom + --flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')" env: AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }} - + run-testinfra: needs: build-run-image if: ${{ success() }} uses: ./.github/workflows/testinfra-ami-build.yml - + run-tests: needs: build-run-image if: ${{ success() }} diff --git a/.github/workflows/testinfra-ami-build.yml b/.github/workflows/testinfra-ami-build.yml index 8544f1b85..321430c86 100644 --- a/.github/workflows/testinfra-ami-build.yml +++ b/.github/workflows/testinfra-ami-build.yml @@ -37,7 +37,7 @@ jobs: ubuntu_release: focal ubuntu_version: 20.04 mcpu: neoverse-n1 - runs-on: ${{ matrix.runner }} + runs-on: ${{ matrix.runner }} timeout-minutes: 150 permissions: contents: write @@ -73,7 +73,7 @@ jobs: echo 'postgres-version = "'$PG_VERSION'"' > common-nix.vars.pkr.hcl # Ensure there's a newline at the end of the file echo "" >> common-nix.vars.pkr.hcl - + - name: Build AMI stage 1 run: | packer init amazon-arm64-nix.pkr.hcl @@ -84,7 +84,7 @@ jobs: run: | packer init stage2-nix-psql.pkr.hcl GIT_SHA=${{github.sha}} - packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "postgres-version=${{ steps.random.outputs.random_string }}" -var "region=ap-southeast-1" -var 'ami_regions=["ap-southeast-1"]' -var "force-deregister=true" -var "git_sha=${GITHUB_SHA}" stage2-nix-psql.pkr.hcl + packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "postgres-version=${{ steps.random.outputs.random_string }}" -var "region=ap-southeast-1" -var 'ami_regions=["ap-southeast-1"]' -var "force-deregister=true" -var "git_sha=${GITHUB_SHA}" stage2-nix-psql.pkr.hcl - name: Run tests timeout-minutes: 10 @@ -93,8 +93,8 @@ jobs: run: | # TODO: use poetry for pkg mgmt pip3 install boto3 boto3-stubs[essential] docker ec2instanceconnectcli pytest pytest-testinfra[paramiko,docker] requests - pytest -vv -s testinfra/test_ami_nix.py - + pytest -vv -s testinfra/test_ami_nix.py + - name: Cleanup resources on build cancellation if: ${{ cancelled() }} run: | @@ -111,7 +111,7 @@ jobs: # Define AMI name patterns STAGE1_AMI_NAME="supabase-postgres-ci-ami-test-stage-1" STAGE2_AMI_NAME="${{ steps.random.outputs.random_string }}" - + # Function to deregister AMIs by name pattern deregister_ami_by_name() { local ami_name_pattern=$1 @@ -121,7 +121,7 @@ jobs: aws ec2 deregister-image --region ap-southeast-1 --image-id $ami_id done } - + # Deregister AMIs deregister_ami_by_name "$STAGE1_AMI_NAME" deregister_ami_by_name "$STAGE2_AMI_NAME" diff --git a/ansible/files/permission_check.py b/ansible/files/permission_check.py index a753f69ec..46f458f9a 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"} ], + "supabase-admin-agent": [ + {"groupname": "supabase-admin-agent", "username": "supabase-admin-agent"}, + {"groupname": "admin", "username": "supabase-admin-agent"}, + {"groupname": "salt", "username": "supabase-admin-agent"}, + ], } # 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", + "supabase-admin-agent", ] 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/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf b/ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf new file mode 100644 index 000000000..6896e2f0c --- /dev/null +++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf @@ -0,0 +1,2 @@ +%supabase-admin-agent ALL= NOPASSWD: /usr/bin/salt-call +%supabase-admin-agent ALL= NOPASSWD: /usr/bin/gpg --homedir {{ gpgdir }} --import, /usr/bin/gpg --homedir {{ gpgdir }} --list-secret-keys * diff --git a/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service new file mode 100644 index 000000000..92f1d2e31 --- /dev/null +++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service @@ -0,0 +1,19 @@ +[Unit] +Description=Configuration management via supabase-admin-agent salt +After=network.target + +[Service] +Type=oneshot +ExecStart=/opt/supabase-admin-agent/supabase-admin-agent --config /opt/supabase-admin-agent/config.yaml salt --apply --store-result +User=supabase-admin-agent +Group=supabase-admin-agent +StandardOutput=journal +StandardError=journal +StateDirectory=supabase-admin-agent +CacheDirectory=supabase-admin-agent + +# Security hardening +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer new file mode 100644 index 000000000..8044c2e1a --- /dev/null +++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer @@ -0,0 +1,13 @@ +[Unit] +Description=Run Supabase supabase-admin-agent salt on a schedule +Requires=supabase-admin-agent_salt.service + +[Timer] +OnCalendar=*:0/10 +# Random delay up to {{ splay }} seconds splay +RandomizedDelaySec={{ splay }} +AccuracySec=1s +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml new file mode 100644 index 000000000..9c6ac0931 --- /dev/null +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -0,0 +1,87 @@ +- name: supabase-admin-agent - system group + group: + name: supabase-admin-agent + system: yes + +- name: supabase-admin-agent - system user + user: + name: supabase-admin-agent + group: supabase-admin-agent + groups: admin,salt + append: yes + system: yes + shell: /bin/sh + +- name: supabase-admin-agent - config dir + file: + path: /opt/supabase-admin-agent + owner: supabase-admin-agent + state: directory + +- name: supabase-admin-agent - gpg dir + file: + path: /etc/salt/gpgkeys + owner: root + group: salt + state: directory + +- name: give supabase-admin-agent user permissions + copy: + src: files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf + dest: /etc/sudoers.d/supabase-admin-agent + 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 supabase-admin-agent archive + get_url: + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}_linux_{{ arch }}.tar.gz" + dest: "/tmp/supabase-admin-agent.tar.gz" + timeout: 90 + +- name: supabase-admin-agent - unpack archive in /opt + unarchive: + remote_src: yes + src: /tmp/supabase-admin-agent.tar.xz + dest: /opt/supabase-admin-agent/ + owner: supabase-admin-agent + extra_opts: + - --strip-components=1 + +- name: supabase-admin-agent - create symlink + ansible.builtin.file: + path: /opt/supabase-admin-agent/supabase-admin-agent + src: "/opt/supabase-admin-agent/supabase-admin-agent-linux-{{ arch }}" + state: link + owner: supabase-admin-agent + mode: "0755" + force: yes + +- name: supabase-admin-agent - create salt systemd timer file + copy: + src: files/supabase_admin_agent_config/supabase-admin-agent_salt.timer + dest: /etc/systemd/system/supabase-admin-agent_salt.timer + +- name: supabase-admin-agent - create salt service file + copy: + src: files/supabase_admin_agent_config/supabase-admin-agent_salt.service + dest: /etc/systemd/system/supabase-admin-agent_salt.service + +- name: supabase-admin-agent - reload systemd + systemd: + daemon_reload: yes + +# Initially ensure supabase-admin-agent is installed but not started +- name: supabase-admin-agent - DISABLE service + systemd: + name: supabase-admin-agent_salt + enabled: no + state: stopped diff --git a/ansible/tasks/setup-supabase-internal.yml b/ansible/tasks/setup-supabase-internal.yml index 7aa931763..d5583b597 100644 --- a/ansible/tasks/setup-supabase-internal.yml +++ b/ansible/tasks/setup-supabase-internal.yml @@ -34,19 +34,19 @@ aws configure set default.s3.use_dualstack_endpoint true - name: install Vector for logging - become: yes + become: true apt: deb: "{{ vector_x86_deb }}" when: platform == "amd64" - name: install Vector for logging - become: yes + become: true apt: deb: "{{ vector_arm_deb }}" when: platform == "arm64" - name: add Vector to postgres group - become: yes + become: true shell: cmd: | usermod -a -G postgres vector @@ -72,21 +72,21 @@ daemon_reload: yes - name: Create checkpoints dir - become: yes + become: true file: path: /var/lib/vector state: directory owner: vector - name: Include file for generated optimizations in postgresql.conf - become: yes + become: true replace: path: /etc/postgresql/postgresql.conf regexp: "#include = '/etc/postgresql-custom/generated-optimizations.conf'" replace: "include = '/etc/postgresql-custom/generated-optimizations.conf'" - name: Include file for custom overrides in postgresql.conf - become: yes + become: true replace: path: /etc/postgresql/postgresql.conf regexp: "#include = '/etc/postgresql-custom/custom-overrides.conf'" @@ -115,5 +115,10 @@ tags: - aws-only +- name: Install supabase-admin-agent + import_tasks: internal/supabase-admin-agent.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 7a7147353..26b2dfcfa 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.098-orioledb" - postgres17: "17.4.1.048" - postgres15: "15.8.1.105" + postgresorioledb-17: "17.0.1.099-orioledb" + postgres17: "17.4.1.049" + postgres15: "15.8.1.106" # Non Postgres Extensions pgbouncer_release: "1.19.0" @@ -54,6 +54,7 @@ postgres_exporter_release_checksum: adminapi_release: 0.84.1 adminmgr_release: 0.25.1 +supabase_admin_agent_release: 1.4.35 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" From d94d15fdb3af0856534fb93e88e51d157269b89a Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Wed, 2 Jul 2025 11:03:06 +0100 Subject: [PATCH 2/6] chore: bump saa --- ansible/vars.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/vars.yml b/ansible/vars.yml index 26b2dfcfa..1d24249ad 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -54,7 +54,7 @@ postgres_exporter_release_checksum: adminapi_release: 0.84.1 adminmgr_release: 0.25.1 -supabase_admin_agent_release: 1.4.35 +supabase_admin_agent_release: 1.4.36 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" From 5c05d99cc363e0ad4aa23ed6183a02167f7a8083 Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Wed, 2 Jul 2025 11:57:43 +0100 Subject: [PATCH 3/6] chore: underscore versus dashes --- ansible/tasks/internal/supabase-admin-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index 9c6ac0931..5c31464e5 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -43,7 +43,7 @@ - name: Download supabase-admin-agent archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}_linux_{{ arch }}.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" dest: "/tmp/supabase-admin-agent.tar.gz" timeout: 90 From 4d4e8dcd681045880eb38dfd2ea338554f1c5801 Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:58:33 +0100 Subject: [PATCH 4/6] chore: correc the uri --- ansible/tasks/internal/supabase-admin-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index 5c31464e5..87402d27b 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -43,7 +43,7 @@ - name: Download supabase-admin-agent archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.us-east-1.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" dest: "/tmp/supabase-admin-agent.tar.gz" timeout: 90 From 88d61a5e66631740cae7d85137fb07b20d5e2760 Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:48:35 +0100 Subject: [PATCH 5/6] chore: omg squash this later --- ansible/tasks/internal/supabase-admin-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index 87402d27b..470435aec 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -43,7 +43,7 @@ - name: Download supabase-admin-agent archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.us-east-1.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent_{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" dest: "/tmp/supabase-admin-agent.tar.gz" timeout: 90 From af00ba3101856816fe1c9fd0e5c11525c184da3c Mon Sep 17 00:00:00 2001 From: Crispy1975 <12525875+Crispy1975@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:46:23 +0100 Subject: [PATCH 6/6] chore: xz to gz for saa --- ansible/tasks/internal/supabase-admin-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index 470435aec..4e5f87e5e 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -50,7 +50,7 @@ - name: supabase-admin-agent - unpack archive in /opt unarchive: remote_src: yes - src: /tmp/supabase-admin-agent.tar.xz + src: /tmp/supabase-admin-agent.tar.gz dest: /opt/supabase-admin-agent/ owner: supabase-admin-agent extra_opts: