diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 61e7d6e314..ec4c7e3b85 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -267,6 +267,8 @@ jobs: qemu: needs: builds-aarch64-linux uses: $/.github/workflows/qemu-image-build.yml + secrets: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} check: name: CI ✅ diff --git a/.github/workflows/qemu-image-build.yml b/.github/workflows/qemu-image-build.yml index 1391c95146..db0dedacf7 100644 --- a/.github/workflows/qemu-image-build.yml +++ b/.github/workflows/qemu-image-build.yml @@ -2,6 +2,10 @@ name: Build QEMU image on: workflow_call: + secrets: + DEV_AWS_ROLE: + description: AWS role used to fetch the supa-tripwire archive + required: true inputs: arch: description: Guest architecture (amd64 is experimental and publishes only to staging) @@ -44,11 +48,18 @@ jobs: artifact: ${{ inputs.publish && format('qemu-image-{0}', inputs.arch || 'arm64') || '' }} permissions: contents: read + id-token: write steps: - name: Checkout Repo uses: actions/checkout@v7.0.1 + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v6.3.0 + with: + role-to-assume: ${{ secrets.DEV_AWS_ROLE }} + aws-region: us-east-1 + - name: Install Nix uses: $/.github/actions/install-nix diff --git a/.github/workflows/qemu-image-release.yml b/.github/workflows/qemu-image-release.yml index 60fc6af7bf..f63d4e72cb 100644 --- a/.github/workflows/qemu-image-release.yml +++ b/.github/workflows/qemu-image-release.yml @@ -23,6 +23,11 @@ permissions: jobs: build: uses: $/.github/workflows/qemu-image-build.yml + permissions: + contents: read + id-token: write + secrets: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} with: arch: ${{ inputs.arch || 'arm64' }} publish: true diff --git a/ansible/files/supa_tripwire/install.sh b/ansible/files/supa_tripwire/install.sh new file mode 100755 index 0000000000..4ca66aa2ed --- /dev/null +++ b/ansible/files/supa_tripwire/install.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# Usage: [SUPA_TRIPWIRE_URL=] install.sh +# SUPA_TRIPWIRE_URL is a presigned URL, or an s3:// URL to presign with the caller's AWS credentials. +# Defaults to the internal artifacts bucket. Safe to rerun on a live host. +set -euo pipefail + +version=$1 +arch=$2 +sha256=$3 + +archive=supa-tripwire-v$version-$arch.tar.xz +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT + +url=${SUPA_TRIPWIRE_URL:-s3://supabase-internal-artifacts/supa-tripwire/$archive} +[[ $url != s3://* ]] || url=$(aws s3 presign --region ap-southeast-1 "$url") +curl -fsSL --retry 3 -o "$tmp/$archive" "$url" +echo "$sha256 $tmp/$archive" | sha256sum -c --quiet - + +tar -xJf "$tmp/$archive" -O "supa-tripwire-v$version-$arch-linux-musl" >/usr/local/bin/supa-tripwire.new +chmod 0755 /usr/local/bin/supa-tripwire.new +mv -f /usr/local/bin/supa-tripwire.new /usr/local/bin/supa-tripwire + +cat >/usr/local/bin/supa-tripwire-wrapped <<'WRAPPER' +#!/usr/bin/env bash + +POSTGRES_BIN=$(readlink -f $(which postgres)) +POSTGRES_DIR=$(dirname "$POSTGRES_BIN") +WRAPPED="$POSTGRES_DIR/.postgres-wrapped" + +if [ -f "$WRAPPED" ]; then + TARGET="$WRAPPED" +else + TARGET="$POSTGRES_BIN" +fi + +exec /usr/local/bin/supa-tripwire "$TARGET" +WRAPPER +chmod 0755 /usr/local/bin/supa-tripwire-wrapped + +[[ -e /etc/supa-tripwire.env ]] || install -m 0600 /dev/null /etc/supa-tripwire.env + +cat >/etc/systemd/system/supa-tripwire.service <<'UNIT' +# /etc/systemd/system/supa-tripwire.service +[Unit] +Description=supa-tripwire - Postgres badness monitor +After=postgresql.service + +[Service] +User=root +Restart=always +RestartSec=5 + +EnvironmentFile=/etc/supa-tripwire.env + +ExecStart=/usr/local/bin/supa-tripwire-wrapped + +NoNewPrivileges=true +SecureBits=no-setuid-fixup-locked +ProtectSystem=strict +ProtectHome=true + +[Install] +WantedBy=multi-user.target +UNIT + +systemctl daemon-reload || true +systemctl enable supa-tripwire +if systemctl is-active --quiet supa-tripwire; then + systemctl restart supa-tripwire +fi diff --git a/ansible/tasks/setup-supabase-internal.yml b/ansible/tasks/setup-supabase-internal.yml index 8c8e9ec7ad..bb326d037a 100644 --- a/ansible/tasks/setup-supabase-internal.yml +++ b/ansible/tasks/setup-supabase-internal.yml @@ -94,6 +94,13 @@ ansible.builtin.import_tasks: file: internal/admin-mgr.yml +- name: Install supa-tripwire + ansible.builtin.script: + cmd: "files/supa_tripwire/install.sh {{ supa_tripwire_release }} {{ platform }} {{ supa_tripwire_sha256[platform] }}" + environment: + SUPA_TRIPWIRE_URL: "{{ lookup('ansible.builtin.env', 'SUPA_TRIPWIRE_URL') }}" + when: lookup('ansible.builtin.env', 'SUPA_TRIPWIRE_URL') | length > 0 + - name: Install adminapi ansible.builtin.import_tasks: file: internal/admin-api.yml diff --git a/ansible/vars.yml b/ansible/vars.yml index 2ddb6b6058..0b62cfc36b 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -37,6 +37,10 @@ adminmgr_artifacts: arm64: url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/admin-mgr/v{{ adminmgr_release }}/admin-mgr_{{ adminmgr_release }}_linux_arm64.tar.gz" checksum: sha256:3477bb0c4dc8e6fea72b1237558cf048de675e211021f9790ef7c134e7452cf3 +supa_tripwire_release: 0.2.0 +supa_tripwire_sha256: + amd64: 7d81ce39815d8f1f1732153b753987271f6e9a84838cfdc4e538f44927b746ef + arm64: cf2e6486d53626fff1312f45500bcacad418dd49eed83560dd58e28a0ec9432d aws_cli_release: 2.23.11 aws_cli_artifacts: amd64: diff --git a/nix/packages/build-ami/build-ami.sh b/nix/packages/build-ami/build-ami.sh index 001cd495ca..67634f9e7a 100644 --- a/nix/packages/build-ami/build-ami.sh +++ b/nix/packages/build-ami/build-ami.sh @@ -123,6 +123,9 @@ common_packer_args=( # both templates require the same plugins, so one init covers both stages packer init -var-file "packer/$arch.vars.pkr.hcl" packer/stage1-nix.pkr.hcl +SUPA_TRIPWIRE_URL=$(aws s3 presign --region ap-southeast-1 --expires-in 3600 "s3://supabase-internal-artifacts/supa-tripwire/supa-tripwire-v$(yq -er .supa_tripwire_release ansible/vars.yml)-$arch.tar.xz" || true) +export SUPA_TRIPWIRE_URL + echo "::group::AMI Build: Stage 1" packer build "${common_packer_args[@]}" \ diff --git a/nix/packages/build-qemu-image/build-qemu-image.sh b/nix/packages/build-qemu-image/build-qemu-image.sh index 957d5bf54e..eb6dd7d8cb 100644 --- a/nix/packages/build-qemu-image/build-qemu-image.sh +++ b/nix/packages/build-qemu-image/build-qemu-image.sh @@ -57,6 +57,8 @@ postgres_version=$(yq -er ".postgres_release.postgres$postgres_major_version" an cloud-localds "$workdir/seeds-cloudimg.iso" user-data-cloudimg meta-data nix_store_paths=$(cat "$(nix build --no-link --print-out-paths "github:supabase/postgres/$git_sha#packages.$system.nix-store-paths-$postgres_major_version")") +SUPA_TRIPWIRE_URL=$(aws s3 presign --region ap-southeast-1 --expires-in 3600 "s3://supabase-internal-artifacts/supa-tripwire/supa-tripwire-v$(yq -er .supa_tripwire_release ansible/vars.yml)-$arch.tar.xz" || true) +export SUPA_TRIPWIRE_URL export LC_ALL=C.UTF-8 export TZ=UTC packer init packer/qemu.pkr.hcl diff --git a/nix/packages/build-qemu-image/default.nix b/nix/packages/build-qemu-image/default.nix index 94762f6f47..93838e218d 100644 --- a/nix/packages/build-qemu-image/default.nix +++ b/nix/packages/build-qemu-image/default.nix @@ -1,4 +1,5 @@ { + awscli2, cloud-utils, coreutils, gitMinimal, @@ -11,6 +12,7 @@ writeShellApplication { name = "build-qemu-image"; runtimeInputs = [ + awscli2 cloud-utils coreutils gitMinimal diff --git a/packer/qemu.pkr.hcl b/packer/qemu.pkr.hcl index e307d37e07..2d16b76d97 100644 --- a/packer/qemu.pkr.hcl +++ b/packer/qemu.pkr.hcl @@ -10,6 +10,11 @@ variable "postgres_major_version" { default = "" } +variable "supa_tripwire_url" { + type = string + default = env("SUPA_TRIPWIRE_URL") +} + # Working dir to pick up non-source files and put output files variable "workdir" { type = string @@ -112,7 +117,8 @@ build { provisioner "shell" { environment_vars = [ "NIX_STORE_PATHS=${jsonencode({ nix_store_paths = var.nix_store_paths })}", - "POSTGRES_MAJOR_VERSION=${var.postgres_major_version}" + "POSTGRES_MAJOR_VERSION=${var.postgres_major_version}", + "SUPA_TRIPWIRE_URL=${var.supa_tripwire_url}" ] use_env_var_file = true script = "packer/scripts/qemu-bootstrap-nix.sh" diff --git a/packer/stage1-nix.pkr.hcl b/packer/stage1-nix.pkr.hcl index 7ee3c0b993..e9d8269ecf 100644 --- a/packer/stage1-nix.pkr.hcl +++ b/packer/stage1-nix.pkr.hcl @@ -1,3 +1,8 @@ +variable "supa_tripwire_url" { + type = string + default = env("SUPA_TRIPWIRE_URL") +} + variable "ami_name" { type = string } @@ -233,6 +238,7 @@ build { environment_vars = [ "POSTGRES_MAJOR_VERSION=${var.postgres_major_version}", "POSTGRES_SUPABASE_VERSION=${var.postgres-version}", + "SUPA_TRIPWIRE_URL=${var.supa_tripwire_url}", ] use_env_var_file = true script = "packer/scripts/surrogate-bootstrap-nix.sh"